2026-07-08 16:17:50 +08:00

219 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
页面未来社区九九社区主页 还原设计稿 liuyuanxitong-yidong/pages/community/community.vue
内容为静态 mock ../data.js挂到首页金刚区未来社区跳转目标
-->
<template>
<view class="fc-page">
<!-- 头部 -->
<view class="fc-hd" :style="{ paddingTop: statusBarTop + 'px' }">
<view class="fc-hd-bar">
<view class="fc-back" @tap="goBack"><u-icon name="arrow-left" color="#1a1a1a" size="38"></u-icon></view>
<text class="fc-hd-title">九九社区</text>
</view>
<view class="fc-loc" @tap="goSelect">
<u-icon name="map" color="#e9272d" size="26"></u-icon>
<text class="fc-loc-txt">{{ locationInfo.community }}</text>
<u-icon name="arrow-down" color="#9098a0" size="20"></u-icon>
</view>
</view>
<view class="fc-body">
<!-- 轮播 -->
<swiper class="fc-hero" :autoplay="true" :interval="4000" :duration="500" circular indicator-dots
indicator-active-color="#fff" indicator-color="rgba(255,255,255,0.5)">
<swiper-item v-for="s in heroSlides" :key="s.key">
<view class="fc-hero-slide" :style="{ background: s.bg }">
<view class="fc-hero-mask"></view>
<view class="fc-hero-copy">
<text class="fc-hero-title">{{ s.title }}</text>
<text class="fc-hero-sub">{{ s.subtitle }}</text>
</view>
</view>
</swiper-item>
</swiper>
<!-- 快捷入口 -->
<view class="fc-shortcut">
<view class="fc-sc-item" v-for="s in shortcuts" :key="s.key" @tap="onShortcut(s)">
<view class="fc-sc-icon" :style="{ background: s.bg }">
<u-icon :name="s.icon" color="#fff" size="40"></u-icon>
</view>
<text class="fc-sc-label">{{ s.label }}</text>
</view>
</view>
<!-- 社区公告 -->
<view class="fc-sec-head">
<view class="fc-sec-left"><text class="fc-sec-bar"></text><text class="fc-sec-title">社区公告</text></view>
<text class="fc-sec-more" @tap="goNoticeList">查看更多 </text>
</view>
<view class="fc-notice-panel">
<view class="fc-notice" v-for="n in topNotices" :key="n.id" @tap="goNoticeDetail(n)">
<view class="fc-notice-icon"><u-icon :name="n.icon" color="#e43f43" size="34"></u-icon></view>
<view class="fc-notice-main">
<text class="fc-notice-title">{{ n.title }}</text>
<text class="fc-notice-sum">{{ n.summary }}</text>
</view>
<view class="fc-notice-aside">
<text class="fc-tag" :style="tagStyle(n.tag)">{{ tagLabel(n.tag) }}</text>
<text class="fc-notice-date">{{ n.date }}</text>
</view>
</view>
</view>
<!-- 社区活动 -->
<view class="fc-sec-head">
<view class="fc-sec-left"><text class="fc-sec-bar"></text><text class="fc-sec-title">社区活动</text></view>
<text class="fc-sec-more" @tap="goActivityList">查看更多 </text>
</view>
<view class="fc-act-list">
<view class="fc-act" v-for="a in topActivities" :key="a.id" @tap="goActivityDetail(a)">
<view class="fc-act-cover">
<image v-if="a.image" :src="a.image" class="fc-act-img" mode="aspectFill" />
<view v-else class="fc-act-img" :style="{ background: sceneBg(a.scene) }"></view>
<text class="fc-act-badge" :style="statusStyle(a.status)">{{ statusLabel(a.status) }}</text>
</view>
<view class="fc-act-info">
<text class="fc-act-title">{{ a.title }}</text>
<text class="fc-act-fee">{{ a.fee || '免费' }}</text>
<text class="fc-act-sub">{{ a.subtitle }}</text>
<view class="fc-act-row"><u-icon name="clock" color="#9098a0" size="22"></u-icon><text>{{ a.time }}</text></view>
<view class="fc-act-row"><u-icon name="map" color="#9098a0" size="22"></u-icon><text>{{ a.place }}</text></view>
<view class="fc-act-foot">
<view class="fc-act-row"><u-icon name="account" color="#9098a0" size="22"></u-icon><text>{{ a.enrolled }}</text></view>
<text class="fc-act-btn" :class="{ done: isJoined(a.id) }" @tap.stop="onJoin(a)">{{ isJoined(a.id) ? '已报名' : '立即报名' }}</text>
</view>
</view>
</view>
</view>
<view class="fc-spacer"></view>
</view>
</view>
</template>
<script>
import { NavgateTo } from '@/utils'
import {
locationInfo, shortcuts, heroSlides, notices, activities,
NOTICE_TAG_META, ACTIVITY_STATUS_META, ACTIVITY_SCENE_BG,
isActivityJoined, toggleActivityJoin
} from '../data.js'
export default {
data() {
return {
statusBarTop: 20,
locationInfo, shortcuts, heroSlides,
topNotices: notices.slice(0, 3),
topActivities: activities.filter(a => a.status !== 'ended').slice(0, 2),
joinedIds: []
}
},
onLoad() {
const sys = uni.getSystemInfoSync()
this.statusBarTop = sys.statusBarHeight || 20
},
onShow() {
this.joinedIds = activities.filter(a => isActivityJoined(a.id)).map(a => a.id)
},
methods: {
tagLabel(t) { return (NOTICE_TAG_META[t] || {}).label || '' },
tagStyle(t) { const m = NOTICE_TAG_META[t] || {}; return { color: m.color, background: m.bg } },
statusLabel(s) { return (ACTIVITY_STATUS_META[s] || {}).label || '' },
statusStyle(s) { const m = ACTIVITY_STATUS_META[s] || {}; return { color: m.color, background: m.bg } },
sceneBg(s) { return ACTIVITY_SCENE_BG[s] || ACTIVITY_SCENE_BG.handicraft },
isJoined(id) { return this.joinedIds.includes(id) },
goBack() { uni.navigateBack({ delta: 1, fail: () => NavgateTo('/pages/index2/index2') }) },
goSelect() { uni.showToast({ title: '当前社区:' + this.locationInfo.community, icon: 'none' }) },
onShortcut(s) {
const map = {
notice: '/packages/futureCommunity/noticeList/index',
activity: '/packages/futureCommunity/activityList/index',
phone: '/packages/futureCommunity/conveniencePhone/index',
house: '/packages/community/index/index',
goodshop: '/packages/localLife/index/index'
}
if (map[s.key]) NavgateTo(map[s.key], { isLogin: false })
else uni.showToast({ title: s.label + '功能开发中', icon: 'none' })
},
goNoticeList() { NavgateTo('/packages/futureCommunity/noticeList/index', { isLogin: false }) },
goActivityList() { NavgateTo('/packages/futureCommunity/activityList/index', { isLogin: false }) },
goNoticeDetail(n) { NavgateTo('/packages/futureCommunity/noticeDetail/index?id=' + n.id, { isLogin: false }) },
goActivityDetail(a) { NavgateTo('/packages/futureCommunity/activityDetail/index?id=' + a.id, { isLogin: false }) },
onJoin(a) {
if (a.status === 'ended') { uni.showToast({ title: '活动已结束', icon: 'none' }); return }
const joined = toggleActivityJoin(a.id)
this.joinedIds = activities.filter(x => isActivityJoined(x.id)).map(x => x.id)
uni.showToast({ title: joined ? '报名成功' : '已取消报名', icon: 'none' })
}
}
}
</script>
<style scoped>
page { background: #f5f6f7; }
.fc-page { min-height: 100vh; background: #f5f6f7; }
/* 头部 */
.fc-hd { position: sticky; top: 0; z-index: 100; background: #fff; padding: 0 24rpx 16rpx; }
.fc-hd-bar { position: relative; display: flex; align-items: center; justify-content: center; height: 80rpx; }
.fc-back { position: absolute; left: 0; top: 0; height: 80rpx; display: flex; align-items: center; }
.fc-hd-title { font-size: 34rpx; font-weight: 700; color: #1a1a1a; }
.fc-loc { display: flex; align-items: center; }
.fc-loc-txt { margin: 0 8rpx; font-size: 26rpx; color: #333; }
.fc-body { padding: 20rpx; }
/* 轮播 */
.fc-hero { width: 100%; height: 286rpx; border-radius: 24rpx; overflow: hidden; }
.fc-hero-slide { position: relative; width: 100%; height: 286rpx; }
.fc-hero-mask { position: absolute; inset: 0; background: linear-gradient(90deg, rgba(40,25,20,0.5) 0%, rgba(40,25,20,0.04) 72%); }
.fc-hero-copy { position: absolute; left: 36rpx; bottom: 46rpx; z-index: 2; display: flex; flex-direction: column; }
.fc-hero-title { font-size: 40rpx; font-weight: 800; color: #fff; }
.fc-hero-sub { margin-top: 10rpx; font-size: 24rpx; color: rgba(255,255,255,0.92); }
/* 快捷入口 */
.fc-shortcut { display: flex; justify-content: space-between; background: #fff; border-radius: 22rpx; padding: 28rpx 16rpx; margin-top: 20rpx; }
.fc-sc-item { display: flex; flex-direction: column; align-items: center; }
.fc-sc-icon { width: 92rpx; height: 92rpx; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.fc-sc-label { margin-top: 14rpx; font-size: 24rpx; color: #333; }
/* 分区标题 */
.fc-sec-head { display: flex; align-items: center; justify-content: space-between; margin: 32rpx 4rpx 18rpx; }
.fc-sec-left { display: flex; align-items: center; }
.fc-sec-bar { width: 6rpx; height: 30rpx; background: #e9272d; border-radius: 3rpx; margin-right: 14rpx; }
.fc-sec-title { font-size: 32rpx; font-weight: 700; color: #1a1a1a; }
.fc-sec-more { font-size: 24rpx; color: #9aa0a8; }
/* 公告 */
.fc-notice-panel { background: #fff; border-radius: 22rpx; padding: 6rpx 24rpx; }
.fc-notice { display: flex; align-items: center; padding: 24rpx 0; border-bottom: 1rpx solid #f2f3f5; }
.fc-notice:last-child { border-bottom: none; }
.fc-notice-icon { flex-shrink: 0; width: 64rpx; height: 64rpx; border-radius: 50%; background: #fff1f1; display: flex; align-items: center; justify-content: center; margin-right: 18rpx; }
.fc-notice-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.fc-notice-title { font-size: 28rpx; font-weight: 600; color: #1a1a1a; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.fc-notice-sum { margin-top: 8rpx; font-size: 22rpx; color: #9098a0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.fc-notice-aside { flex-shrink: 0; margin-left: 16rpx; display: flex; flex-direction: column; align-items: flex-end; }
.fc-tag { font-size: 20rpx; padding: 2rpx 12rpx; border-radius: 6rpx; }
.fc-notice-date { margin-top: 10rpx; font-size: 20rpx; color: #b6bcc4; }
/* 活动 */
.fc-act-list { display: flex; flex-direction: column; }
.fc-act { display: flex; background: #fff; border-radius: 22rpx; overflow: hidden; margin-bottom: 20rpx; }
.fc-act-cover { position: relative; width: 260rpx; flex-shrink: 0; }
.fc-act-img { width: 260rpx; height: 100%; min-height: 220rpx; display: block; }
.fc-act-badge { position: absolute; left: 12rpx; top: 12rpx; font-size: 20rpx; padding: 2rpx 12rpx; border-radius: 6rpx; }
.fc-act-info { position: relative; flex: 1; min-width: 0; padding: 18rpx 20rpx; display: flex; flex-direction: column; }
.fc-act-title { font-size: 30rpx; font-weight: 700; color: #1a1a1a; max-width: 280rpx; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.fc-act-fee { position: absolute; right: 20rpx; top: 18rpx; font-size: 24rpx; color: #e9272d; font-weight: 700; }
.fc-act-sub { margin-top: 8rpx; font-size: 22rpx; color: #9098a0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.fc-act-row { display: flex; align-items: center; margin-top: 10rpx; font-size: 22rpx; color: #6b7078; }
.fc-act-row text { margin-left: 8rpx; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.fc-act-foot { display: flex; align-items: center; justify-content: space-between; margin-top: 14rpx; }
.fc-act-btn { flex-shrink: 0; background: linear-gradient(90deg, #ff5b5b 0%, #ef111b 100%); color: #fff; font-size: 22rpx; padding: 8rpx 24rpx; border-radius: 26rpx; }
.fc-act-btn.done { background: #eef0f3; color: #9aa0a8; }
.fc-spacer { height: 40rpx; }
</style>