daoGuanNotice.vue 6.05 KB
<template>
  <view class="notice-page">
    <z-paging
      ref="paging"
      v-model="dataList"
      class="notice-paging"
      emptyViewImg="/static/nodata.png"
      @query="queryList"
    >
      <template #top>
        <view class="notice-hero">
          <view class="hero-title-row">
            <view>
              <view class="hero-title">中国跆拳道协会</view>
              <view class="hero-subtitle">CHINESE TAEKWONDO ASSOCIATION</view>
            </view>
            <view class="hero-page-title">
              <text>协会资讯</text>
              <view class="title-line"></view>
            </view>
          </view>

          <!-- <view class="search-bar">
            <uni-easyinput
              v-model="query.keyword"
              :input-border="false"
              class="search-input"
              placeholder="请输入公告标题"
              placeholderStyle="font-size:28rpx;color:#999"
              prefixIcon="search"
              @confirm="handleSearch"
              @clear="handleSearch"
            />
            <view class="search-btn" @click="handleSearch">搜索</view>
          </view> -->
        </view>

        <!-- <view class="notice-tabs">
          <view class="tab-item active">公告</view>
        </view> -->
      </template>

      <view class="notice-list">
        <view v-for="item in dataList" :key="item.id || item.noteId" class="notice-item" @click="goDetail(item)">
          <view class="notice-title">{{ item.name || item.title || '--' }}</view>
          <view v-if="item.introduction || item.remark || item.content" class="notice-summary">
            {{ item.introduction || item.remark || item.content }}
          </view>
          <image
            v-if="getCover(item)"
            :src="getCover(item)"
            class="notice-cover"
            mode="aspectFill"
          />
          <view class="notice-meta">
            <text>{{ formatDate(item.belongTime || item.createTime || item.publishTime) }}</text>
            <!-- <view class="meta-right">
              <text class="heart">♡</text>
              <text>{{ item.readNum || item.views || item.likeNum || 0 }}</text>
              <text class="more">...</text>
            </view> -->
          </view>
        </view>
      </view>
    </z-paging>

    <dao-guan-tab-bar :currentIndex="2" @switch="onTabSwitch" />
  </view>
</template>

<script setup>
import { ref, reactive } from 'vue'
import * as api from '@/common/api.js'
import dayjs from 'dayjs'
import DaoGuanTabBar from '@/components/dao-guan-tab-bar.vue'

const dataList = ref([])
const paging = ref(null)
const query = reactive({
  keyword: ''
})

const queryList = (pageNum, pageSize) => {
  api.notice({
    pageNum,
    pageSize,
    name: query.keyword
  }).then(res => {
    paging.value?.complete(res.rows || [])
  }).catch(() => {
    paging.value?.complete(false)
  })
}

const handleSearch = () => {
  paging.value?.reload()
}

const getCover = (item) => {
  return item.coverUrl || item.cover || item.picUrl || item.imageUrl || item.imgUrl || ''
}

const formatDate = (value) => {
  if (!value) return ''
  return dayjs(value).format('YYYY-MM-DD')
}

const goDetail = (item) => {
  uni.navigateTo({
    url: `/pages/index/newsDetail?noteId=${item.noteId}`
  })
}

const onTabSwitch = () => {
  // tab switch handled by component
}
</script>

<style lang="scss" scoped>
.notice-page {
  position: relative;
  height: 100vh;
  overflow: hidden;
  background: #ededf0;
  box-sizing: border-box;
}

.notice-hero {
  padding: calc(env(safe-area-inset-top) + 88rpx) 40rpx 34rpx;
  background: linear-gradient(135deg, #b00005 0%, #760000 100%);
  color: #fff;
}

.hero-title-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 42rpx;
}

.hero-title {
  font-size: 38rpx;
  letter-spacing: 2rpx;
}

.hero-subtitle {
  margin-top: 8rpx;
  color: rgba(255, 255, 255, 0.6);
  font-size: 16rpx;
}

.hero-page-title {
  color: #f4b536;
  font-size: 36rpx;
  font-weight: 500;
  text-align: right;
}

.title-line {
  width: 54rpx;
  height: 6rpx;
  margin: 14rpx 0 0 auto;
  border-radius: 10rpx;
  background: #f4b536;
}

.search-bar {
  display: flex;
  align-items: center;
  height: 64rpx;
  border-radius: 34rpx;
  background: #fff;
  overflow: hidden;
}

.search-input {
  flex: 1;

  :deep(.uni-easyinput__content) {
    height: 64rpx;
    padding: 0 18rpx 0 28rpx;
    border-radius: 34rpx;
    background: #fff;
  }
}

.search-btn {
  width: 88rpx;
  height: 52rpx;
  margin-right: 6rpx;
  border-radius: 28rpx;
  background: #c91c34;
  color: #fff;
  font-size: 24rpx;
  font-weight: 700;
  line-height: 52rpx;
  text-align: center;
}

.notice-tabs {
  display: flex;
  align-items: center;
  padding: 24rpx 40rpx 8rpx;
}

.tab-item {
  position: relative;
  margin-right: 54rpx;
  padding-bottom: 14rpx;
  color: #555;
  font-size: 30rpx;
}

.tab-item.active {
  color: #c30d23;
  font-weight: 700;
}

.tab-item.active::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 52rpx;
  height: 4rpx;
  border-radius: 4rpx;
  background: #c30d23;
  transform: translateX(-50%);
}

.notice-paging {
  height: 100vh;
  background: #ededf0;
}

.notice-list {
  padding: 0 10rpx calc(160rpx + env(safe-area-inset-bottom));
}

.notice-item {
  margin-bottom: 34rpx;
  background: #fff;
  padding: 24rpx;
  border-radius: 16rpx;
  margin: 20rpx;
}

.notice-title {
  color: #111;
  font-size: 31rpx;
  font-weight: 800;
  line-height: 1.42;
}

.notice-summary {
  display: -webkit-box;
  margin-top: 12rpx;
  overflow: hidden;
  color: #666;
  font-size: 25rpx;
  line-height: 1.45;
  text-overflow: ellipsis;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.notice-cover {
  width: 100%;
  height: 330rpx;
  margin-top: 14rpx;
  border-radius: 0;
  background: #ddd;
}

.notice-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 10rpx;
  color: #999;
  font-size: 24rpx;
}

.meta-right {
  display: flex;
  align-items: center;
  gap: 8rpx;
}

.heart {
  font-size: 28rpx;
}

.more {
  margin-left: 14rpx;
  letter-spacing: 2rpx;
}
</style>