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

79 lines
3.9 KiB
Vue

<!-- 未来社区 - 公告详情 -->
<template>
<view class="nd-page">
<view class="fc-nav" :style="{ paddingTop: statusBarTop + 'px' }">
<view class="fc-nav-bar">
<view class="fc-back" @tap="goBack"><u-icon name="arrow-left" color="#1a1a1a" size="38"></u-icon></view>
<text class="fc-nav-title">公告详情</text>
</view>
</view>
<view class="nd-body" v-if="notice">
<view class="nd-card">
<text class="fc-tag" :style="tagStyle(notice.tag)">{{ tagLabel(notice.tag) }}</text>
<text class="nd-title">{{ notice.title }}</text>
<view class="nd-meta">
<u-icon name="clock" color="#b6bcc4" size="22"></u-icon>
<text>{{ notice.date }}</text>
<text class="nd-meta-dot">·</text>
<text>上河坊·九九社区</text>
</view>
<rich-text class="nd-content" :nodes="notice.content"></rich-text>
</view>
<view class="fc-spacer"></view>
</view>
<view v-else class="fc-empty">公告不存在</view>
<view class="nd-foot" v-if="notice">
<text class="nd-share" @tap="onShare">分享</text>
<text class="nd-follow" :class="{ on: followed }" @tap="onFollow">{{ followed ? '已关注' : '关注公告' }}</text>
</view>
</view>
</template>
<script>
import { findNotice, NOTICE_TAG_META, isNoticeFollowed, toggleNoticeFollow } from '../data.js'
export default {
data() { return { statusBarTop: 20, notice: null, followed: false } },
onLoad(options) {
const sys = uni.getSystemInfoSync()
this.statusBarTop = sys.statusBarHeight || 20
this.notice = findNotice(options && options.id) || null
if (this.notice) this.followed = isNoticeFollowed(this.notice.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 } },
goBack() { uni.navigateBack({ delta: 1 }) },
onShare() { uni.showToast({ title: '分享功能开发中', icon: 'none' }) },
onFollow() { this.followed = toggleNoticeFollow(this.notice.id); uni.showToast({ title: this.followed ? '已关注' : '已取消关注', icon: 'none' }) }
}
}
</script>
<style scoped>
page { background: #f5f6f7; }
.nd-page { min-height: 100vh; background: #f5f6f7; padding-bottom: 130rpx; }
.fc-nav { position: sticky; top: 0; z-index: 100; background: #fff; padding: 0 24rpx 16rpx; }
.fc-nav-bar { position: relative; display: flex; align-items: center; justify-content: center; height: 88rpx; }
.fc-back { position: absolute; left: 0; top: 0; height: 88rpx; display: flex; align-items: center; }
.fc-nav-title { font-size: 34rpx; font-weight: 700; color: #1a1a1a; }
.nd-body { padding: 20rpx; }
.nd-card { background: #fff; border-radius: 20rpx; padding: 30rpx; }
.fc-tag { display: inline-block; font-size: 22rpx; padding: 4rpx 16rpx; border-radius: 6rpx; }
.nd-title { display: block; font-size: 38rpx; font-weight: 800; color: #1a1a1a; margin-top: 18rpx; line-height: 1.4; }
.nd-meta { display: flex; align-items: center; margin-top: 18rpx; font-size: 22rpx; color: #b6bcc4; }
.nd-meta text { margin-left: 6rpx; }
.nd-meta-dot { margin: 0 10rpx; }
.nd-content { display: block; margin-top: 24rpx; font-size: 28rpx; color: #333; line-height: 1.8; }
.nd-foot { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; display: flex; align-items: center; gap: 20rpx; padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); box-shadow: 0 -4rpx 20rpx rgba(0,0,0,0.04); }
.nd-share { flex: 1; text-align: center; font-size: 30rpx; color: #333; border: 1rpx solid #e5e5e5; border-radius: 44rpx; padding: 18rpx 0; }
.nd-follow { flex: 1; text-align: center; font-size: 30rpx; color: #fff; background: linear-gradient(90deg, #ff5b5b 0%, #ef111b 100%); border-radius: 44rpx; padding: 18rpx 0; }
.nd-follow.on { background: #eef0f3; color: #9aa0a8; }
.fc-empty { text-align: center; color: #9aa0a8; font-size: 26rpx; padding: 120rpx 0; }
.fc-spacer { height: 20rpx; }
</style>