|
@@ -0,0 +1,290 @@
|
|
|
+<route lang="json5" type="page">
|
|
|
+{
|
|
|
+ layout: 'default',
|
|
|
+ style: {
|
|
|
+ navigationStyle: 'custom',
|
|
|
+ },
|
|
|
+}
|
|
|
+</route>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+// 必须导入需要用到的页面生命周期(即使在当前页面上没有直接使用到)
|
|
|
+// eslint-disable-next-line unused-imports/no-unused-imports
|
|
|
+import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
|
|
|
+import { onMounted, onUnmounted } from 'vue'
|
|
|
+import useZPaging from 'z-paging/components/z-paging/js/hooks/useZPaging.js'
|
|
|
+
|
|
|
+defineOptions({
|
|
|
+ name: 'ProductDetail', // 商品详情
|
|
|
+})
|
|
|
+// 获取屏幕边界到安全区域距离
|
|
|
+const systemInfo = uni.getSystemInfoSync()
|
|
|
+const safeAreaInsets = systemInfo.safeAreaInsets
|
|
|
+
|
|
|
+// z-paging
|
|
|
+const paging = ref(null)
|
|
|
+// 类似mixins,如果是页面滚动务必要写这一行,并传入当前ref绑定的paging,注意此处是paging,而非paging.value
|
|
|
+useZPaging(paging)
|
|
|
+
|
|
|
+// 添加导航栏背景色变量
|
|
|
+const navBgColor = ref('transparent')
|
|
|
+const navIconType = ref('tr') // tr表示透明背景下的图标,默认为白色图标
|
|
|
+const changeNavbarThreshold = 300 // 滚动到这个高度时改变导航栏颜色
|
|
|
+
|
|
|
+onPageScroll((e) => {
|
|
|
+ // 根据滚动高度改变导航栏背景色
|
|
|
+ if (e.scrollTop > changeNavbarThreshold) {
|
|
|
+ navBgColor.value = '#ffffff'
|
|
|
+ navIconType.value = '' // 切换为深色图标
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ navBgColor.value = 'transparent'
|
|
|
+ navIconType.value = 'tr' // 切换为白色图标
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 搜索结果
|
|
|
+// 轮播图
|
|
|
+const current = ref<number>(0)
|
|
|
+const swiperList = ref([
|
|
|
+ '/static/images/avatar.jpg',
|
|
|
+ '/static/images/vip-info-bg.png',
|
|
|
+ '/static/images/vip-level1.png',
|
|
|
+])
|
|
|
+
|
|
|
+// 添加通知轮播数据
|
|
|
+const notifications = ref([
|
|
|
+ { id: 1, name: 'Aamir Khan', time: '10s' },
|
|
|
+ { id: 2, name: 'John Smith', time: '30s' },
|
|
|
+ { id: 3, name: 'Maria Garcia', time: '1m' },
|
|
|
+])
|
|
|
+const notificationIndex = ref(0)
|
|
|
+// 添加上一个索引的记录,用于判断动画方向
|
|
|
+const prevNotificationIndex = ref(0)
|
|
|
+
|
|
|
+// 设置通知轮播定时器
|
|
|
+let notificationTimer: number | null = null
|
|
|
+
|
|
|
+// 生命周期钩子中启动轮播
|
|
|
+onMounted(() => {
|
|
|
+ startNotificationCarousel()
|
|
|
+})
|
|
|
+
|
|
|
+// 组件卸载时清除定时器
|
|
|
+onUnmounted(() => {
|
|
|
+ if (notificationTimer) {
|
|
|
+ clearInterval(notificationTimer)
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 启动通知轮播
|
|
|
+function startNotificationCarousel() {
|
|
|
+ notificationTimer = setInterval(() => {
|
|
|
+ // 保存当前索引
|
|
|
+ prevNotificationIndex.value = notificationIndex.value
|
|
|
+
|
|
|
+ // 更新为下一个索引
|
|
|
+ notificationIndex.value = (notificationIndex.value + 1) % notifications.value.length
|
|
|
+ }, 1500) // 每1.5秒切换一次
|
|
|
+}
|
|
|
+
|
|
|
+function handleClick(e) {
|
|
|
+ // console.log(e)
|
|
|
+}
|
|
|
+function onChange(e) {
|
|
|
+ // console.log(e)
|
|
|
+}
|
|
|
+
|
|
|
+// 添加头像列表数据
|
|
|
+const avatarList = ref([
|
|
|
+ '/static/images/avatar.jpg',
|
|
|
+ '/static/images/avatar.jpg',
|
|
|
+ '/static/images/avatar.jpg',
|
|
|
+ '/static/images/avatar.jpg',
|
|
|
+ '/static/images/avatar.jpg',
|
|
|
+ '/static/images/avatar.jpg',
|
|
|
+ '/static/images/avatar.jpg',
|
|
|
+])
|
|
|
+
|
|
|
+const dataList = ref([])
|
|
|
+function queryList(pageNo, pageSize) {
|
|
|
+ // 此处请求仅为演示,请替换为自己项目中的请求
|
|
|
+ setTimeout(() => {
|
|
|
+ dataList.value = [
|
|
|
+ { title: '123' },
|
|
|
+ { title: '123' },
|
|
|
+ { title: '123' },
|
|
|
+ { title: '12345' },
|
|
|
+ ]
|
|
|
+ paging.value.complete(dataList.value)
|
|
|
+ }, 1000)
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <z-paging ref="paging" refresher-only use-page-scroll @query="queryList">
|
|
|
+ <wd-navbar :bordered="false" safe-area-inset-top fixed :left-arrow="false" :custom-style="`background: ${navBgColor}; transition: background 0.3s;`" custom-class="h-auto!">
|
|
|
+ <template #title>
|
|
|
+ <view class="box-border h-full flex items-center justify-between p-24rpx">
|
|
|
+ <image :src="`/static/icons/left-icon${navBgColor === '#ffffff' ? '-tr' : ''}.png`" class="h-56rpx w-56rpx" />
|
|
|
+ <image :src="`/static/icons/menu-icon${navBgColor === '#ffffff' ? '-tr' : ''}.png`" class="h-56rpx w-56rpx" />
|
|
|
+ </view>
|
|
|
+ </template>
|
|
|
+ </wd-navbar>
|
|
|
+ <view class="relative">
|
|
|
+ <wd-swiper
|
|
|
+ v-model:current="current" :list="swiperList" autoplay height="750rpx"
|
|
|
+ custom-indicator-class="bottom-40rpx!" :indicator="{ type: 'fraction' }" indicator-position="bottom-right"
|
|
|
+ image-mode="aspectFit" @click="handleClick" @change="onChange"
|
|
|
+ />
|
|
|
+ <view class="absolute left-24rpx h-56rpx w-70% overflow-hidden rounded-full" :style="{ top: `${safeAreaInsets?.top + 52}px` }">
|
|
|
+ <view
|
|
|
+ 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"
|
|
|
+ :style="{
|
|
|
+ opacity: index === notificationIndex ? 1 : 0,
|
|
|
+ transform: index === notificationIndex ? 'translateY(0)'
|
|
|
+ : (index === prevNotificationIndex ? 'translateY(-100%)' : 'translateY(100%)'),
|
|
|
+ position: 'absolute',
|
|
|
+ top: 0,
|
|
|
+ left: 0,
|
|
|
+ width: '100%',
|
|
|
+ zIndex: index === notificationIndex ? 2 : 1,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <wd-img width="40rpx" round height="40rpx" src="/static/images/avatar.jpg" />
|
|
|
+ <text class="ml-12rpx truncate text-24rpx text-white">
|
|
|
+ {{ notification.name }} joined this group {{ notification.time }} ago!
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="relative -top-24rpx">
|
|
|
+ <view
|
|
|
+ class="flex items-center justify-between rounded-t-24rpx from-[#FF3779] to-[#FF334A] bg-gradient-to-br px-24rpx pb-24rpx pt-18rpx text-white"
|
|
|
+ >
|
|
|
+ <view>
|
|
|
+ <view class="mb-12rpx flex items-center">
|
|
|
+ <text class="text-28rpx">
|
|
|
+ Price
|
|
|
+ </text>
|
|
|
+ <view class="ml-8rpx rounded-t-18rpx rounded-br-18rpx bg-#202221 px-12rpx text-24rpx">
|
|
|
+ 20GB
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view>
|
|
|
+ <text class="text-48rpx">
|
|
|
+ <text class="text-28rpx">
|
|
|
+ ৳
|
|
|
+ </text>1000.00
|
|
|
+ </text>
|
|
|
+ <text class="ml-22rpx text-28rpx line-through">
|
|
|
+ ৳1999.00
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <text class="text-28rpx">
|
|
|
+ 1.8k sold
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ <view class="bg-white px-24rpx pb-24rpx pt-20rpx text-32rpx">
|
|
|
+ <view class="line-clamp-2font-bold mb-16rpx">
|
|
|
+ BOLON Classic Aviator Polarized Sunglasses, Exclusive Eyewear Brand
|
|
|
+ </view>
|
|
|
+ <view class="flex items-center justify-between">
|
|
|
+ <view>
|
|
|
+ <text class="mr-20rpx">
|
|
|
+ Color
|
|
|
+ </text>
|
|
|
+ <text class="text-#757575">
|
|
|
+ Black Grey
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ <wd-icon name="arrow-right" color="#7D7D7D" size="36rpx" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="mb-20rpx bg-white p-24rpx">
|
|
|
+ <view class="mb-20rpx flex items-center justify-between">
|
|
|
+ <view
|
|
|
+ class="flex items-center before:h-45rpx before:w-8rpx before:rounded-4rpx before:bg-#FF3778 before:content-empty"
|
|
|
+ >
|
|
|
+ <text class="ml-10rpx text-32rpx">
|
|
|
+ Group Rules
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ <view class="flex items-center">
|
|
|
+ <text class="mr-8rpx text-24rpx text-#3A444C">
|
|
|
+ View Rules
|
|
|
+ </text>
|
|
|
+ <wd-icon name="arrow-right" color="#7D7D7D" size="24rpx" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <image src="/static/images/buy-flow.png" class="w-full" mode="widthFix" />
|
|
|
+ </view>
|
|
|
+ <view class="bg-white p-24rpx">
|
|
|
+ <view
|
|
|
+ class="mb-20rpx flex items-center before:h-45rpx before:w-8rpx before:rounded-4rpx before:bg-#FF3778 before:content-empty"
|
|
|
+ >
|
|
|
+ <text class="ml-10rpx text-32rpx">
|
|
|
+ Ongoing Group
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ <view class="flex flex-col gap-24rpx">
|
|
|
+ <view v-for="i in 3" :key="i" class="flex items-center justify-between">
|
|
|
+ <view class="flex items-center">
|
|
|
+ <view>
|
|
|
+ <!-- 头像组 最多五个 -->
|
|
|
+ <view class="mr-16rpx flex items-center">
|
|
|
+ <view
|
|
|
+ v-for="(avatar, index) in avatarList.slice(0, 5)"
|
|
|
+ :key="index"
|
|
|
+ :style="{ marginLeft: index !== 0 ? '-20rpx' : '0', zIndex: 10 - index }"
|
|
|
+ class="h-56rpx w-56rpx overflow-hidden border-2rpx border-white rounded-full border-solid"
|
|
|
+ >
|
|
|
+ <image :src="avatar" class="h-full w-full" mode="aspectFill" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view>
|
|
|
+ <view class="text-28rpx font-bold">
|
|
|
+ Need <text class="text-[var(--wot-color-theme)]">
|
|
|
+ 5
|
|
|
+ </text> More
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <wd-button size="small">
|
|
|
+ Join Group
|
|
|
+ </wd-button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="bg-white p-24rpx">
|
|
|
+ <view
|
|
|
+ class="mb-20rpx flex items-center before:h-45rpx before:w-8rpx before:rounded-4rpx before:bg-#FF3778 before:content-empty"
|
|
|
+ >
|
|
|
+ <text class="ml-10rpx text-32rpx">
|
|
|
+ Details
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ <view v-for="i in 3" :key="i">
|
|
|
+ <image
|
|
|
+ src="/static/images/avatar.jpg"
|
|
|
+ mode="widthFix"
|
|
|
+ class="w-full"
|
|
|
+ />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </z-paging>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+:deep() {
|
|
|
+ .wd-navbar__title {
|
|
|
+ margin: 0;
|
|
|
+ max-width: 100%;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|