fuyuan-housekeeping-uniapp/src/pages/index/index.vue

481 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="container">
<view class="main">
<z-paging
ref="paging"
v-model="indexDataArr"
@query="upCallback"
@scroll="pagingScroll"
@scrolltoupper="scrolltoupper"
:fixed="false"
height="100%"
auto-show-back-to-top
>
<view class="top_container">
<view
class="title text-[#1b4694] font-bold text-5xl"
:style="{
top: statusBarHeight + 'px',
height: navHeight + 'px',
lineHeight: navHeight + 'px'
}"
>
{{ titleImageObj[0]?.content?.title ?? '思缘生活' }}
</view>
<template v-if="searchList">
<w-search
:content="searchList?.content"
:styles="searchList?.styles"
:navbarStyle="{ top: titleHeight + 10 + 'px' }"
/>
</template>
<image
:style="{ height: 70 + titleHeight + 'px' }"
:src="getImageUrl(item.image)"
v-for="(item, ind) in titleImageObj[0]?.content?.data"
:key="ind"
/>
</view>
<!-- 固定顶部搜索栏 -->
<view
class="top_fixed fixed bg-white w-[100%] top-0 z-[99]"
:style="{ height: titleHeight + 8 + 'px' }"
v-if="searchFixed"
>
<template v-if="searchList">
<w-search
:content="searchList?.content"
:styles="searchList?.styles"
:navbarStyle="{ bottom: '13px', height: capsuleHeight + 'px' }"
:navbarItemStyle="{ background: '#F1F1F1' }"
:inputStyle="{ width: '250rpx' }"
/>
</template>
</view>
<view>
<view
v-for="(item, index) in indexData.pages"
:key="index"
class="bg-[#F5F5F7]"
>
<!-- <template v-if="item.name == 'search'">
<w-search :content="item.content" :styles="item.styles" />
</template> -->
<template v-if="item.name == 'banner'">
<w-banner :content="item.content" :styles="item.styles" />
</template>
<template v-if="item.name == 'nav'">
<w-nav :content="item.content" :styles="item.styles" />
</template>
<template v-if="item.name == 'category'">
<w-category :content="item.content" :styles="item.styles" />
</template>
</view>
<template v-if="activityList?.length">
<ActivateIndoor :lists="activityList"></ActivateIndoor>
</template>
<!-- -->
<view
v-for="(item, index) in indexData.pages"
:key="index"
class="bg-[#F5F5F7]"
>
<template v-if="item.name == 'category'">
<CategoryDatalist :content="item.content" />
</template>
</view>
</view>
<!-- 活动专区:假节日搞活动 -->
<!-- <template v-if="indexData?.promotion?.length">
<ActivateIndoor :lists="indexData.promotion"></ActivateIndoor>
</template> -->
<!-- 新品推荐 -->
<!-- <template v-if="indexData?.newRecommend?.length">
<NewGoods :lists="indexData.newRecommend"></NewGoods>
</template> -->
<!-- 热门服务 -->
<!-- <template v-if="indexData?.hotService?.length">
<hot :lists="indexData.hotService"></hot>
</template> -->
<!-- 吸顶分类 -->
<template v-if="categoryList?.length > 0">
<stickyCategory
ref="stickycategory"
:lists="categoryList"
:top="titleHeight"
@tabChange="tabChange"
:isFixed="isFixed"
></stickyCategory>
</template>
<!-- 师傅推荐 暂时屏掉,参考竞品,一般不显示 -->
<!-- <template v-if="indexData?.staff?.length">
<master :lists="indexData.staff"></master>
</template> -->
<!-- 推荐分类 -->
<!-- <template v-if="indexData?.category.length || []">
<category :lists="indexData?.category"></category>
</template> -->
<!-- 用于占位 -->
<div class="cat" v-if="indexData?.hotService.length"></div>
</z-paging>
</view>
<view class="right-btns">
<view class="rightcontrol" @click="rightControl">
<!-- <image
class="iamge-close"
src="@/static/images/icon_clear.png"
alt=""
v-if="isShowRightBtn"
/> -->
</view>
<!-- <view class="allBtn" v-if="isShowRightBtn">
<button class="button" type="default" open-type="share">
<image src="@/static/images/share.png" alt="" />
<view>分享</view>
</button>
<button class="button" type="default" @click="call">
<image src="@/static/images/phone.png" alt="" />
<view>电话</view>
</button>
<button class="button" type="default" open-type="contact">
<image src="@/static/images/kefu.png" alt="" />
<view>客服</view>
</button>
</view> -->
</view>
<view class="endrightcontrol" @click="rightControl">
<image src="@/static/images/icon_user_about.png" alt="" v-if="!isShowRightBtn" />
</view>
<!-- 底部导航栏 -->
<Tabbar />
</view>
</template>
<script setup lang="ts">
import { getIndex } from '@/api/shop'
import { reactive, shallowRef, ref, unref } from 'vue'
import { onLoad, onUnload, onShareAppMessage, onShow } from '@dcloudio/uni-app'
import Tabbar from '@/components/tabbar/tabbar.vue'
// import Category from './comp/category.vue'
import ActivateIndoor from './comp/activate-indoor.vue'
// import NewGoods from './comp/new-goods.vue'
// import Hot from './comp/hot-list.vue'
// import Master from './comp/master-list.vue'
import CategoryDatalist from './comp/category-datalist.vue'
import stickyCategory from './comp/sticky-category.vue'
import { useAppStore } from '@/stores/app'
import { getDecorate } from '@/api/shop'
import { useUserStore } from '@/stores/user'
import { apiActivityList } from '@/api/goods'
import { storeToRefs } from 'pinia'
const appStore = useAppStore()
const userStore = useUserStore()
const { userInfo } = storeToRefs(userStore)
const paging = shallowRef()
const { getImageUrl } = useAppStore()
const indexData = reactive<any>({
pages: [],
promotion: [],
newRecommend: [],
hotService: [],
staff: [],
category: []
})
interface ListContent {
content?: {
title: ''
data: [
{
image: ''
}
]
}
styles?: {}
title?: ''
}
interface ListContentList {
[index: number]: ListContent
}
interface ActivityList {
goodsIds: string | null
id: number
name: string
status: number
surfacePlot: string
}
let categoryList = reactive([]) //分类
let searchList = reactive<ListContent>({}) //搜索
const activityList = ref<ActivityList[]>([]) //活动专区
let titleImageObj = reactive<ListContentList>([]) //顶部图片标题
const titleHeight = ref(0) //标题栏总高度
const capsuleHeight = ref(0) //胶囊高度
const navHeight = ref(0) //导航栏高度
const statusBarHeight = ref(0) //状态栏高度
const getTitleHeight = () => {
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
uni.getSystemInfo({
success: res => {
statusBarHeight.value = res?.statusBarHeight as number
navHeight.value =
(menuButtonInfo.top - statusBarHeight.value) * 2 + menuButtonInfo.height //获取导航栏高度
titleHeight.value = statusBarHeight.value + navHeight.value
capsuleHeight.value = menuButtonInfo.height
}
})
}
//z-paging直接绑定indexData控制台会报警告[Vue warn]: Invalid prop: type check failed for prop "modelValue". Expected Array, got Object
//故定义indexDataArr
interface IndexArray {
content: object
disabled: boolean
display: boolean
id: string
name: string
styles: object
title: string
}
let indexDataArr: IndexArray[] = []
const upCallback = async (): Promise<void> => {
try {
const data = await getIndex({
cityId: appStore.cityInfo.city_id
})
for (const key in indexData) {
if (data[key] != null && data[key] != undefined) {
indexData[key] = data[key]
}
}
indexData.pages = JSON.parse(data.pages)
indexDataArr = new Array(indexData.pages)
console.log('indexData.pages', indexData.pages)
// 吸顶分类列表
const cate_list = indexData.pages.filter((i: any) => i.name == 'sticky-category')
if (cate_list.length > 0) {
categoryList = cate_list[0].content.data
}
// 搜索栏
const search_list = indexData.pages.filter((i: any) => i.name == 'search')
if (search_list.length > 0) {
searchList = search_list[0]
}
// 顶部图片标题信息
titleImageObj = indexData.pages.filter((i: any) => i.name == 'home-title')
// 导航菜单(金刚区)
paging.value.complete([data])
} catch (err) {
console.log(err)
// refreshRef.value.endErr()
paging.value.complete(false)
}
}
onShow(async () => {
const res = await apiActivityList({ status: 1 })
activityList.value = res.lists
})
const stickycategory = ref()
const searchFixed = ref(false) //显示顶部搜索栏
const pagingScroll = async (e: any) => {
const banner_h = uni.upx2px(300) //300为顶部图片的高度
const sc_top = e.detail.scrollTop
stickycategory?.value?.handleActive(sc_top)
if (sc_top > banner_h) searchFixed.value = true
else searchFixed.value = false
}
const isFixed = ref(true)
const scrolltoupper = () => {
// 解决点击返回顶部按钮返回顶部后,还有吸顶的问题
isFixed.value = false
setTimeout(() => {
isFixed.value = true
})
}
// 吸顶分类改变
const tabChange = async (e: any) => {
paging.value.scrollToY(e)
}
onShareAppMessage(() => {
return {
title: `粤好生活`,
imageUrl: '',
path: `/pages/index/index?scene=${unref(userInfo).distributorId}`
}
})
const call = async () => {
// 获取页面装修-客服设置中配置的客服联系电话
const data = await getDecorate({ id: 3 })
const datas = JSON.parse(data.pages)
const mobile = datas[0].content.mobile
uni.makePhoneCall({
phoneNumber: mobile,
success: function () {
console.log('拨打电话成功')
},
fail: function () {
console.log('拨打电话失败')
}
})
}
// const sharedState = inject('sharedState')
onLoad(options => {
// 扫描普通二维码
// 有distId重新扫码进来
// 有distId,重新扫新码
// #ifdef MP-WEIXIN
// const q = decodeURIComponent(options.q)
// if (q.indexOf('distributorId=') != -1) {
// // 已绑定且已登录
// if (userStore.distId && userStore.token) return
// const distributorId = parseFloat(q.split('distributorId=')[1])
// userStore.setDistId(distributorId)
// if (userStore.token) {
// userStore.bindingDistId()
// }
// }
// 扫太阳码或分享
const { scene } = options
if (scene) {
const distributorId = parseFloat(scene)
userStore.setDistId(distributorId)
if (userStore.token) {
userStore.bindingDistId()
}
}
// #endif
getTitleHeight()
uni.$on('refreshhome', () => {
upCallback()
})
})
onUnload(() => {
uni.$off('refreshhome')
})
const isShowRightBtn = ref(true)
const rightControl = () => {
isShowRightBtn.value = !isShowRightBtn.value
}
</script>
<style lang="scss">
.container {
display: flex;
height: 100vh;
overflow: hidden;
flex-direction: column;
font-family: 'Source Han Sans CN', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
.main {
flex: 1;
min-height: 0;
overflow: scroll;
background: #f8f8f9;
position: relative;
// background-color: #fff;
}
.top_container {
// position: absolute;
image {
width: 100%;
// height: 300rpx;
vertical-align: top;
}
.title {
position: absolute;
// top: 93rpx;
left: 50%;
transform: translateX(-50%);
}
}
.right-btns {
position: fixed;
right: 20rpx;
bottom: 25%;
width: 100rpx;
min-height: 35px;
z-index: 1000;
.rightcontrol {
width: 100%;
height: 50rpx;
display: flex;
image {
width: 40rpx;
height: 40rpx;
object-fit: contain;
margin-left: auto;
}
.iamge-close {
background: rgba(34, 39, 21, 0.75);
border-radius: 50%;
}
}
.button {
width: 100rpx;
height: 100rpx;
background: rgba(34, 39, 21, 0.75);
border-radius: 50%;
margin-bottom: 20rpx;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
color: #ffffff;
padding: 0;
image {
width: 35rpx;
height: 35rpx;
object-fit: contain;
}
view {
font-size: 24rpx;
height: 43rpx;
line-height: 43rpx;
}
}
}
.endrightcontrol {
position: fixed;
right: 20rpx;
bottom: 168rpx;
width: 60rpx;
min-height: 40rpx;
z-index: 1000;
display: flex;
image {
width: 40rpx;
height: 40rpx;
object-fit: contain;
}
}
}
</style>