Bladeren bron

feat: 商品详情消息轮播接口对接

liangan 1 maand geleden
bovenliggende
commit
867eeeaecc

+ 7 - 0
src/api/product.ts

@@ -38,3 +38,10 @@ export function getDetail(data: any) {
 export function pinkList(data: any) {
   return http.post<any>(`${pre}/app/pink/ongoing/list`, data)
 }
+/**
+ * 滚动消息轮播
+ * @returns data.list[]
+ */
+export function carousel(id: any) {
+  return http.get<any>(`${pre}/app/product/carousel/${id}`)
+}

+ 3 - 0
src/locale/bn.json

@@ -257,6 +257,9 @@
   "notifications.money.withdrawalFail.title": "উত্তোলন ব্যর্থ",
   "notifications.money.withdrawalFail.content": "আপনার উত্তোলনের অনুরোধ ব্যর্থ হয়েছে",
   "productDetail.title": "পণ্যের বিবরণ",
+  "productDetail.notification.message": "{name} {time} সেকেন্ড আগে এই গ্রুপে {action}!",
+  "productDetail.notification.opened": "খুলেছেন",
+  "productDetail.notification.joined": "যোগ দিয়েছেন",
   "webLink.title": "ওয়েব লিঙ্ক",
   "missionCenter.signIn.title": "ক্রমাগত সাইন ইন করে পুরস্কার পান",
   "missionCenter.signIn.button": "চেক-ইন",

+ 3 - 0
src/locale/en.json

@@ -258,6 +258,9 @@
   "notifications.money.withdrawalFail.title": "Withdrawal Failed",
   "notifications.money.withdrawalFail.content": "Your withdrawal request has been failed",
   "productDetail.title": "Product Detail",
+  "productDetail.notification.message": "{name} {action} this group {time}s ago!",
+  "productDetail.notification.opened": "opened",
+  "productDetail.notification.joined": "joined",
   "webLink.title": "Web Link",
   "missionCenter.signIn.title": "Continuous sign in to receive rewards",
   "missionCenter.signIn.button": "Check-in",

+ 3 - 0
src/locale/zh-Hans.json

@@ -257,6 +257,9 @@
   "notifications.money.withdrawalFail.title": "提现失败",
   "notifications.money.withdrawalFail.content": "您的提现请求已失败",
   "productDetail.title": "产品详情",
+  "productDetail.notification.message": "{name} {time}秒前{action}了这个团购",
+  "productDetail.notification.opened": "发起",
+  "productDetail.notification.joined": "加入",
   "webLink.title": "网页链接",
   "missionCenter.signIn.title": "连续签到获得奖励",
   "missionCenter.signIn.button": "签到",

+ 40 - 26
src/pages/productDetail/components/NotificationCarousel.vue

@@ -1,41 +1,45 @@
-<script lang="ts" setup>
-interface Notification {
-  id: number
-  name: string
-  time: string
-}
-
-interface Props {
-  notifications?: Notification[]
-  interval?: number
-  top?: string
-}
+<script setup>
+import { t } from '@/locale'
 
-const props = withDefaults(defineProps<Props>(), {
-  notifications: () => [
-    { id: 1, name: 'Aamir Khan', time: '10s' },
-    { id: 2, name: 'John Smith', time: '30s' },
-    { id: 3, name: 'Maria Garcia', time: '1m' },
-  ],
-  interval: 3000,
-  top: '0px',
+const props = defineProps({
+  notifications: {
+    type: Array,
+    default: () => [],
+  },
+  interval: {
+    type: Number,
+    default: 3000,
+  },
+  top: {
+    type: String,
+    default: '0px',
+  },
 })
 
 const notificationIndex = ref(0)
 const prevNotificationIndex = ref(0)
-let notificationTimer: number | null = null
+const isAnimating = ref(false)
+let notificationTimer = null
 
 // 启动通知轮播
 function startNotificationCarousel() {
-  if (props.notifications.length <= 1)
+  if (props.notifications.length === 0)
     return
 
   notificationTimer = setInterval(() => {
+    // 触发动画效果
+    isAnimating.value = true
+
     // 保存当前索引
     prevNotificationIndex.value = notificationIndex.value
 
     // 更新为下一个索引
     notificationIndex.value = (notificationIndex.value + 1) % props.notifications.length
+
+    // 动画结束后重置状态
+    setTimeout(() => {
+      isAnimating.value = false
+    }, 300) // 动画持续300ms
   }, props.interval)
 }
 
@@ -90,10 +94,16 @@ defineExpose({
       v-for="(notification, index) in notifications"
       :key="notification.id"
       class="flex items-center rounded-full bg-#000000/60 py-8rpx pl-8rpx pr-14rpx transition-all duration-500 ease-in-out"
+      :class="{
+        'animate-pulse': notifications.length === 1 && isAnimating,
+        'animate-bounce': notifications.length === 1 && isAnimating,
+      }"
       :style="{
         opacity: index === notificationIndex ? 1 : 0,
-        transform: index === notificationIndex ? 'translateY(0)'
-          : (index === prevNotificationIndex ? 'translateY(-100%)' : 'translateY(100%)'),
+        transform: notifications.length === 1
+          ? (isAnimating ? 'translateY(0) scale(1.05)' : 'translateY(0) scale(1)')
+          : (index === notificationIndex ? 'translateY(0)'
+            : (index === prevNotificationIndex ? 'translateY(-100%)' : 'translateY(100%)')),
         position: 'absolute',
         top: 0,
         left: 0,
@@ -101,9 +111,13 @@ defineExpose({
         zIndex: index === notificationIndex ? 2 : 1,
       }"
     >
-      <wd-img width="40rpx" round height="40rpx" src="/static/images/avatar.jpg" />
+      <wd-img width="40rpx" round height="40rpx" :src="notification.headPic" />
       <text class="ml-12rpx truncate text-24rpx text-white">
-        {{ notification.name }} joined this group {{ notification.time }} ago!
+        {{ t('productDetail.notification.message', {
+          name: notification.name,
+          action: notification.kId === 0 ? t('productDetail.notification.opened') : t('productDetail.notification.joined'),
+          time: notification.time,
+        }) }}
       </text>
     </view>
   </view>

+ 7 - 9
src/pages/productDetail/productDetail.vue

@@ -14,7 +14,7 @@ import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
 import useZPaging from 'z-paging/components/z-paging/js/hooks/useZPaging.js'
 import { myFavoriteAdd, myFavoriteDel } from '@/api/mine'
 import { preOrder as _preOrder } from '@/api/order'
-import { getDetail, pinkList } from '@/api/product'
+import { carousel, getDetail, pinkList } from '@/api/product'
 import { requireLogin } from '@/hooks/usePageAuth'
 import { t } from '@/locale'
 import { formatNumber } from '@/utils/index'
@@ -67,6 +67,10 @@ const notifications = ref([
   { id: 2, name: 'John Smith', time: '30s' },
   { id: 3, name: 'Maria Garcia', time: '1m' },
 ])
+async function getCarousel() {
+  const res = await carousel(productId.value)
+  notifications.value = res.data
+}
 // 点击页面任意地方隐藏提示
 function handlePageClick() {
   if (showTip.value) {
@@ -83,13 +87,6 @@ onMounted(() => {
 // 轮播图
 const current = ref<number>(0)
 
-function handleClick(e) {
-  // console.log(e)
-}
-function onChange(e) {
-  // console.log(e)
-}
-
 // 拼团类型 join-加团 open-开团
 const groupType = ref('open')
 const pinkId = ref('') // 拼团id
@@ -312,6 +309,7 @@ onLoad((options) => {
   productId.value = params.productId
 })
 onShow(async () => {
+  getCarousel()
   await queryDetail()
   await queryPinkInfo()
 })
@@ -331,7 +329,7 @@ onShow(async () => {
       <wd-swiper
         v-model:current="current" :list="detail.sliderImage.split(',')" autoplay height="750rpx"
         custom-indicator-class="bottom-40rpx!" :indicator="{ type: 'fraction' }" indicator-position="bottom-right"
-        image-mode="aspectFit" @click="handleClick" @change="onChange"
+        image-mode="aspectFit"
       />
       <NotificationCarousel
         :notifications="notifications"