219 lines
12 KiB
Vue
219 lines
12 KiB
Vue
<!--
|
||
页面:未来社区(九九社区)主页 —— 还原设计稿 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>
|