瀏覽代碼

feat(shop-notice): 接入商城首页公告轮播

- 首页公告条拉取商城首页位置公告,有公告时自动轮播并支持点击进入详情

- 公告详情页统一标题为公告,并在详情加载后同步导航栏标题

- 首页向公告组件传递 account,保证详情请求使用正确门店上下文
shizhongqi 3 天之前
父節點
當前提交
e76f36caa3

+ 1 - 1
mallApp/src/api/shop-notice/index.js

@@ -1,6 +1,6 @@
 import https from '@/plugins/luch-request_0.0.7/request'
 
-/** 客户端公告列表(分类页 position=2) */
+/** 客户端公告列表(首页 position=1 / 分类页 position=2) */
 export const shopNoticeShowList = data => {
 	return https.get('/shop-notice/show-list', data)
 }

+ 84 - 5
mallApp/src/components/home/noticeBar.vue

@@ -1,19 +1,91 @@
 <!--
   店铺首页-公告条
-  纯静态样式展示,暂无后台配置开关;文案先写死,后续如需可再接配置
+  拉取 hdApp「店铺公告」中展示位置为「商城首页」(position=1) 的上架公告;
+  同位置多条时每 6 秒纵向轮播,点击当前条跳转公告详情。
 -->
 <template>
-  <view class="home-notice-bar">
+  <view
+    class="home-notice-bar"
+    v-if="noticeList.length"
+    @tap.stop="openNoticeDetail"
+  >
     <image class="notice-icon" src="/static/images/home/icon-notice-horn.svg" mode="aspectFit" />
     <text class="notice-tag">公告</text>
-    <text class="notice-text">每月11号会员日,会员全场8.8折</text>
+    <swiper
+      class="notice-swiper"
+      :key="'home-notice-' + noticeList.length"
+      vertical
+      :autoplay="noticeList.length > 1"
+      :circular="noticeList.length > 1"
+      :interval="6000"
+      :duration="400"
+      :skip-hidden-item-layout="true"
+      @change="onNoticeChange"
+    >
+      <swiper-item v-for="item in noticeList" :key="item.id">
+        <text class="notice-text">{{ item.summary }}</text>
+      </swiper-item>
+    </swiper>
     <text class="notice-arrow">›</text>
   </view>
 </template>
 
 <script>
+import { shopNoticeShowList } from '@/api/shop-notice'
+
+/** 公告展示位置:商城首页(与 hdApp shopNotice/add positionOptions 一致) */
+const NOTICE_POSITION_HOME = 1
+
 export default {
-  name: 'homeNoticeBar'
+  name: 'homeNoticeBar',
+  props: {
+    /** 店铺 account,跳转详情时带入,保证详情页请求落到正确门店 */
+    account: {
+      type: [String, Number],
+      default: ''
+    }
+  },
+  data() {
+    return {
+      noticeList: [],
+      currentNoticeIndex: 0
+    }
+  },
+  created() {
+    this.loadNoticeList()
+  },
+  methods: {
+    /**
+     * 拉取商城首页公告列表
+     * 无数据时组件自隐藏,避免空条占位
+     */
+    loadNoticeList() {
+      return shopNoticeShowList({ position: NOTICE_POSITION_HOME }).then((res) => {
+        const data = res.data || {}
+        this.noticeList = data.list || []
+        this.currentNoticeIndex = 0
+      }).catch(() => {
+        this.noticeList = []
+      })
+    },
+    /** 记录当前轮播下标,点击时打开对应公告详情 */
+    onNoticeChange(e) {
+      this.currentNoticeIndex = e.detail.current || 0
+    },
+    /**
+     * 跳转公告详情页
+     * 与分类页 notice-bar 一致,走 shop-notice-detail
+     */
+    openNoticeDetail() {
+      const item = this.noticeList[this.currentNoticeIndex]
+      if (!item || !item.id) return
+      const account = this.account || uni.getStorageSync('account') || ''
+      this.$util.pageTo({
+        url: '/pages/home/shop-notice-detail',
+        query: { id: item.id, account }
+      })
+    }
+  }
 }
 </script>
 
@@ -27,6 +99,7 @@ export default {
   border-radius: 32upx;
   background: #FFF0F3;
   box-shadow: 0 2upx 12upx rgba(255, 77, 125, 0.1);
+  box-sizing: border-box;
 }
 .notice-icon {
   flex-shrink: 0;
@@ -46,11 +119,17 @@ export default {
   border-radius: 6upx;
   box-sizing: border-box;
 }
-.notice-text {
+.notice-swiper {
   flex: 1;
+  width: 0;
+  height: 40upx;
   min-width: 0;
+}
+.notice-text {
+  display: block;
   font-size: 24upx;
   color: #FF4D7D;
+  line-height: 40upx;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;

+ 1 - 1
mallApp/src/pages.json

@@ -10,7 +10,7 @@
         { "path": "pages/home/category", "style": { "navigationBarTitleText": "花束" } },
         { "path": "pages/home/shop-category", "style": { "navigationBarTitleText": "分类" } },
         { "path": "pages/home/cart", "style": { "navigationBarTitleText": "购物车", "navigationBarTextStyle": "black" } },
-        { "path": "pages/home/shop-notice-detail", "style": { "navigationBarTitleText": "公告详情" } },
+        { "path": "pages/home/shop-notice-detail", "style": { "navigationBarTitleText": "公告" } },
         { "path": "pages/home/pic-text-detail", "style": { "navigationBarTitleText": "图文详情" } },
         { "path": "pages/home/mall", "style": { "navigationBarTitleText": "相册" } },
         { "path": "pages/home/shop", "style": { "navigationBarTitleText": "门店" } },

+ 1 - 1
mallApp/src/pages/home/index.vue

@@ -29,7 +29,7 @@
               :account="account"
               :hd-id="hdId"
             />
-            <home-notice-bar />
+            <home-notice-bar :account="account" />
           </template>
           <home-nav-grid
             v-else-if="mod.key === 'navGrid'"

+ 7 - 2
mallApp/src/pages/home/shop-notice-detail.vue

@@ -1,11 +1,12 @@
 <!--
   商城公告详情页
-  用途:展示 xhShopNotice 富媒体内容,从分类页通知栏进入
+  用途:展示 xhShopNotice 富媒体内容,从首页/分类页通知栏进入;
+  导航栏标题优先用公告标题,无标题时回落为「公告」
 -->
 <template>
   <view class="notice-detail-page">
     <view class="page-header">
-      <text class="page-title">{{ title || '公告详情' }}</text>
+      <text class="page-title">{{ title || '公告' }}</text>
       <text class="page-summary" v-if="summary">{{ summary }}</text>
     </view>
     <view class="preview-content">
@@ -36,6 +37,8 @@ export default {
   },
   methods: {
     init() {
+      // 进入页先设默认导航标题,详情返回后再换成公告标题
+      uni.setNavigationBarTitle({ title: '公告' })
       this.loadDetail()
     },
     loadDetail() {
@@ -45,6 +48,8 @@ export default {
         if (this.$util.isEmpty(res.data)) return
         this.title = res.data.title || ''
         this.summary = res.data.summary || ''
+        // 导航栏标题:有公告标题用标题,否则保持「公告」
+        uni.setNavigationBarTitle({ title: this.title || '公告' })
         let content = []
         if (typeof res.data.content === 'string') {
           try {