index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. <script setup lang="ts">
  2. import { calcNavSwiperHeight } from './calcNavSwiperHeight'
  3. import { StaticUrl } from '@/config'
  4. import router from '@/router'
  5. definePage({
  6. name: 'smqjh-home',
  7. layout: 'tabbar',
  8. islogin: false,
  9. type: 'home',
  10. style: {
  11. navigationBarTitleText: '首页',
  12. navigationStyle: 'custom',
  13. backgroundColor: '#9ED605',
  14. backgroundColorTop: '#9ED605',
  15. },
  16. })
  17. const { show } = useGlobalToast()
  18. const addressStore = useAddressStore()
  19. const { statusBarHeight, MenuButtonHeight, opcity, isOnlineAudit } = storeToRefs(useSysStore())
  20. const { name } = storeToRefs(addressStore)
  21. const { userInfo, userMemberInfo } = storeToRefs(useUserStore())
  22. const xsbStore = ref<typeof import('@/subPack-xsb/store-xsb/sys')>()
  23. const { data: goodsList, isLastPage, page, reload, error, refresh } = usePagination((pageNum, pageSize) =>
  24. Apis.xsb.getSearchProductList({ data: { pageNum, pageSize, salesNum: 'DESC', shopId: xsbStore.value?.useSysXsbStore().SelectShopInfo.shopId || 2, channelId: userInfo.value.channelId || 1 } }), {
  25. data: resp => resp.data?.list,
  26. initialData: [],
  27. initialPage: 1,
  28. initialPageSize: 10,
  29. append: true,
  30. immediate: false,
  31. })
  32. const state = computed(() => {
  33. return error.value ? 'error' : !isLastPage.value ? 'loading' : 'finished'
  34. })
  35. const currentIndex = ref(0)
  36. const loading = ref(true)
  37. onShow(async () => {
  38. useSysStore().getAudit()
  39. useUserStore().getUserMemberInfo()
  40. useSmqjhCartStore().getCartList('XSB')
  41. getSelectZhUser()
  42. xsbStore.value = await AsyncImport('@/subPack-xsb/store-xsb/sys')
  43. refresh()
  44. })
  45. onMounted(() => {
  46. setTimeout(() => {
  47. loading.value = false
  48. }, 1000)
  49. })
  50. onReachBottom(() => {
  51. if (!isLastPage.value) {
  52. page.value++
  53. }
  54. })
  55. const navList = computed(() => {
  56. const list = [
  57. { icon: `${StaticUrl}/xsb.png`, title: '星闪豹', name: 'xsb-homeTabbar', show: true },
  58. { icon: `${StaticUrl}/smqjh-index-cd.png`, title: '充电', name: 'charge-index', show: true },
  59. { icon: `${StaticUrl}/smqjh-sp.png`, title: '电影演出', name: 'film-index', show: true },
  60. { icon: `${StaticUrl}/smqjh-vip.png`, title: '视频权益', name: 'video-rights-tabbar', show: !isOnlineAudit.value },
  61. { icon: `${StaticUrl}/smqjh-djk.png`, title: '大健康', name: 'djk-homeTabbar', show: true },
  62. { icon: `${StaticUrl}/smqjh-jiayou.png`, title: '加油', name: 'refueling-tabbar', show: true },
  63. { icon: `${StaticUrl}/smqjh-attractions.png`, title: '景区', name: 'attractions-tabbar', show: true },
  64. { icon: `${StaticUrl}/smqjh-diancan.png`, title: '大牌点餐', name: '', show: !isOnlineAudit.value },
  65. { icon: `${StaticUrl}/smqjh-jiudian.png`, title: '酒店民宿', name: '', show: !isOnlineAudit.value },
  66. { icon: `${StaticUrl}/smqjh-daijia.png`, title: '代驾', name: '', show: !isOnlineAudit.value },
  67. ]
  68. return list
  69. })
  70. const itemsPerPage = 8
  71. const columnsCount = 4
  72. const visibleNavList = computed(() => navList.value.filter(i => i.show))
  73. const swiperHeight = computed(() => {
  74. const total = visibleNavList.value.length
  75. return calcNavSwiperHeight(total, currentIndex.value, { itemsPerPage, columns: columnsCount })
  76. })
  77. const swiperStyle = computed(() => ({ height: `${swiperHeight.value}rpx` }))
  78. onMounted(() => {
  79. addressStore.getLocation()
  80. opcity.value = 0
  81. })
  82. onPageScroll((e) => {
  83. const calculatedOpacity = e.scrollTop / 100
  84. opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
  85. })
  86. function handleClick(name: string) {
  87. if (!name) {
  88. show({ msg: '敬请期待 !' })
  89. return
  90. }
  91. if (userInfo.value.channelId === 58 && name !== 'xsb-homeTabbar') {
  92. show({ msg: '您所属的企业暂无权限查看 !' })
  93. return
  94. }
  95. if (name === 'refueling-tabbar') { // 跳转至公众号
  96. // #ifdef MP-WEIXIN
  97. ;(wx as any).openOfficialAccountProfile({
  98. username: 'gh_6a682fa2ed1d',
  99. })
  100. // #endif
  101. // #ifdef H5
  102. router.push({ name: 'refueling-tabbar' })
  103. // #endif
  104. return
  105. }
  106. router.push({ name })
  107. }
  108. onShareAppMessage(() => {
  109. return {
  110. title: '市民请集合',
  111. }
  112. })
  113. const showoverlay = ref(false)
  114. const showoverlay2 = ref(true)
  115. async function getSelectZhUser() {
  116. const res = await Apis.sys.selectZhUser({})
  117. if (res.data.channelId === 54 && !res.data.isClaimed) {
  118. showoverlay.value = true
  119. }
  120. }
  121. async function getZhUserReceived() {
  122. useGlobalLoading().loading({ msg: '领取中...' })
  123. await Apis.sys.zhUserReceived({})
  124. useGlobalLoading().close()
  125. show({ msg: '领取成功 !' })
  126. showoverlay.value = false
  127. }
  128. function handleGo() {
  129. router.push({ name: 'bannerDetaile' })
  130. }
  131. function handleChangeSwiper(e: UniHelper.SwiperOnChangeEvent) {
  132. console.log(e.detail.current, 'e.detail.current')
  133. currentIndex.value = e.detail.current
  134. }
  135. function handleJyBanner() {
  136. // #ifdef MP-WEIXIN
  137. wx.openOfficialAccountArticle({
  138. url: 'https://mp.weixin.qq.com/s/lxpdZ6DUhgqg00AT9klu5Q',
  139. })
  140. // #endif
  141. // #ifdef H5
  142. window.open('https://mp.weixin.qq.com/s/lxpdZ6DUhgqg00AT9klu5Q')
  143. // #endif
  144. }
  145. </script>
  146. <template>
  147. <view class="page-class box-border">
  148. <wd-navbar
  149. title="" :custom-style="`background-color: ${hexToRgba(useManualThemeStore().themeVars.colorTheme as string, opcity)};`" :bordered="false" :z-index="99"
  150. safe-area-inset-top fixed
  151. >
  152. <template #left>
  153. <view class="relative z-10 h-48rpx w-202rpx w-full opacity-100">
  154. <image class="absolute left-0 top-0 h-48rpx w-202rpx" :src="`${StaticUrl}/logo.png`" />
  155. </view>
  156. </template>
  157. </wd-navbar>
  158. <view
  159. class="header-linear h-320rpx px-24rpx"
  160. :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }"
  161. >
  162. <view class="box-border w-full flex items-center">
  163. <view class="flex items-center" @click="useAddressStore().getMapAddress()">
  164. <image :src="`${StaticUrl}/location-black.png`" class="h-33.8rpx min-w-28.97rpx w-28.97rpx" />
  165. <view class="ml-18rpx max-w-180rpx truncate text-32rpx">
  166. {{ name }}
  167. </view>
  168. </view>
  169. <view class="ml-16rpx h-60rpx flex flex-1 items-center justify-between rounded-40rpx bg-white pr-6rpx">
  170. <view class="flex items-center pb-14rpx pl-24rpx pt-16rpx">
  171. <wd-icon name="search" size="14" color="#ccc" />
  172. <view class="ml-12rpx text-24rpx text-gray">
  173. 霸王茶姬
  174. </view>
  175. </view>
  176. <view
  177. class="h-50rpx w-96rpx flex items-center justify-center rounded-26rpx bg-[var(--them-color)] text-24rpx text-white font-semibold"
  178. >
  179. 搜索
  180. </view>
  181. </view>
  182. </view>
  183. </view>
  184. <view class="px-24rpx -mt260rpx">
  185. <view class="mt-24rpx rounded-16rpx bg-white py-24rpx" :class="[loading ? 'px-24rpx' : '']">
  186. <wd-skeleton
  187. :loading="loading"
  188. theme="image" :row-col="[
  189. [
  190. { width: '120rpx', height: '120rpx' },
  191. { width: '120rpx', height: '120rpx' },
  192. { width: '120rpx', height: '120rpx' },
  193. { width: '120rpx', height: '120rpx' },
  194. ],
  195. [
  196. { width: '120rpx', height: '120rpx' },
  197. { width: '120rpx', height: '120rpx' },
  198. { width: '120rpx', height: '120rpx' },
  199. { width: '120rpx', height: '120rpx' },
  200. ],
  201. ]"
  202. >
  203. <!-- h340rpx -->
  204. <swiper :duration="300" :style="swiperStyle" class="transition-height" @change="handleChangeSwiper">
  205. <swiper-item
  206. v-for="pageIndex in Math.ceil(navList.filter(i => i.show).length / 8)" :key="pageIndex"
  207. >
  208. <view class="grid grid-cols-4 gap-12rpx">
  209. <template
  210. v-for="item in navList.filter(i => i.show).slice((pageIndex - 1) * 8, pageIndex * 8)"
  211. :key="item.icon"
  212. >
  213. <view
  214. class="flex flex-col items-center justify-center"
  215. @click="handleClick(String(item.name))"
  216. >
  217. <view class="relative h-120rpx w-120rpx">
  218. <image :src="item.icon" class="h-120rpx w-120rpx" />
  219. <view
  220. v-if="item.name == ''"
  221. class="linebg absolute left-0 top-0 h-full w-full flex items-center justify-center rounded-32rpx text-24rpx text-white font-semibold"
  222. >
  223. 敬请期待
  224. </view>
  225. </view>
  226. <view class="text-24rpx">
  227. {{ item.title }}
  228. </view>
  229. </view>
  230. </template>
  231. </view>
  232. </swiper-item>
  233. </swiper>
  234. <view class="w-full flex items-center justify-center">
  235. <view v-for="_pageIndex, index in Math.ceil(navList.filter(i => i.show).length / 8)" :key="index" class="mr14rpx transition-all transition-duration-400 ease-in" :class="[currentIndex == index ? 'rounded-12rpx w-40rpx h12rpx bg-[var(--them-color)]' : 'w12rpx h12rpx rounded-50% bg-#F0F0F0']" />
  236. </view>
  237. </wd-skeleton>
  238. </view>
  239. <view class="mt-20rpx w-full flex items-center justify-between">
  240. <image :src="`${StaticUrl}/smqjh-jy-banner.jpg`" class="h-346rpx w-344rpx flex-shrink-0 rounded-12rpx" @click="handleJyBanner" />
  241. <view class="flex flex-1 flex-col items-end justify-center" @click="handleGo">
  242. <image :src="`${StaticUrl}/smqjh-home-banner1.jpg`" class="h-180rpx w-344rpx rounded-12rpx" />
  243. <image :src="`${StaticUrl}/smqjh-home-banner2.jpg`" class="mt-14rpx h-152rpx w-344rpx rounded-12rpx" />
  244. </view>
  245. </view>
  246. <view class="mt-20rpx">
  247. <wd-skeleton
  248. theme="image" animation="gradient" :loading="loading"
  249. :row-col="[[{ height: '568rpx', width: '344rpx' }, { height: '568rpx', width: '344rpx' }], [{ height: '568rpx', width: '344rpx' }, { height: '568rpx', width: '344rpx' }]]"
  250. >
  251. <view class="flex items-center">
  252. <view class="w-full columns-2 gap-[10px]">
  253. <view
  254. v-for="item in goodsList" :key="item.id"
  255. class="relative mb-[10px] break-inside-avoid overflow-hidden rounded-16rpx bg-white pb-16rpx"
  256. >
  257. <view @click="router.push({ name: 'xsb-goods', params: { id: item.prodId } })">
  258. <view class="relative h-344rpx">
  259. <image :src="item.pic" class="h-344rpx w-344rpx" />
  260. <image
  261. :src="`${StaticUrl}/xsb-shui-index.png`"
  262. class="absolute left-0 top-0 h-344rpx w-344rpx"
  263. />
  264. <view class="absolute bottom-0 left-0 flex items-center text-22rpx">
  265. <view class="rounded-tl-8rpx bg-[#02ECFD] pl-4rpx">
  266. 星闪豹
  267. </view>
  268. <!-- <view class="rounded-tr-8rpx bg-[rgba(0,0,0,0.5)] pl8rpx pr4rpx text-white">
  269. 峰10:00-13:00
  270. </view> -->
  271. </view>
  272. </view>
  273. <view class="mt-16rpx pl-20rpx pr-6rpx">
  274. <view class="flex items-center">
  275. <!-- <view class="rounded-8rpx bg-#FF4D3A px12rpx text-24rpx text-white">
  276. 补贴
  277. </view> -->
  278. <view class="line-clamp-2 text-28rpx font-semibold">
  279. {{ item.prodName }}
  280. </view>
  281. </view>
  282. <view v-if="item.isMember" class="mt-20rpx flex items-center gap-16rpx">
  283. <view class="flex items-end text-[#FF4D3A]">
  284. <view class="text-24rpx">
  285. </view>
  286. <view class="text-36rpx line-height-[36rpx]">
  287. {{ item.memberPrice }}
  288. </view>
  289. <view class="text-24rpx">
  290. </view>
  291. </view>
  292. <view class="rounded-8rpx bg-#FF4A39 px-8rpx py-4rpx text-22rpx text-#FFF">
  293. 会员价
  294. </view>
  295. <view class="text-24rpx text-#AAA line-through">
  296. ¥{{ item.channelProdPrice }}
  297. </view>
  298. </view>
  299. <view v-else class="mt-20rpx flex items-end text-[#FF4D3A]">
  300. <view class="text-24rpx">
  301. </view>
  302. <view class="text-36rpx line-height-[36rpx]">
  303. {{ item.channelProdPrice }}
  304. </view>
  305. <view class="text-24rpx">
  306. </view>
  307. </view>
  308. </view>
  309. </view>
  310. <view
  311. v-if="!item.spuStock"
  312. class="absolute left-0 top-0 z-1 h-full w-full flex items-center justify-center bg-[rgba(255,255,255,0.6)]"
  313. >
  314. <view
  315. class="h-156rpx w-156rpx flex items-center justify-center rounded-full bg-[rgba(0,0,0,.6)] text-28rpx text-white"
  316. >
  317. 商品已售罄
  318. </view>
  319. </view>
  320. <view
  321. v-if="!item.skuList.some((it) => it.saleStatus)"
  322. class="absolute left-0 top-0 z-1 h-full w-full flex items-center justify-center bg-[rgba(255,255,255,0.6)]"
  323. >
  324. <view
  325. class="h-156rpx w-156rpx flex items-center justify-center rounded-full bg-[rgba(0,0,0,.6)] text-28rpx text-white"
  326. >
  327. 商品不可售
  328. </view>
  329. </view>
  330. </view>
  331. </view>
  332. </view>
  333. </wd-skeleton>
  334. </view>
  335. <wd-loadmore v-if="goodsList.length > 9" :state="state" :loading-props="{ color: '#9ED605', size: 20 }" @reload="reload" />
  336. <wd-overlay :show="showoverlay" @click="showoverlay = false">
  337. <view class="mt-280rpx flex items-center justify-center">
  338. <view class="relative h-906rpx w-644rpx flex flex-col justify-center text-center" :style="{ backgroundImage: `url(${StaticUrl}/home-overlay-img.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }">
  339. <view>
  340. <view class="text-80rpx text-#FF1B51 font-600">
  341. ¥200
  342. </view>
  343. <view class="text-28rpx font-800">
  344. 现金抵扣券
  345. </view>
  346. </view>
  347. <view class="absolute bottom-110rpx left-42% text-60rpx text-#FF1B51 font-bold" @click="getZhUserReceived">
  348. </view>
  349. </view>
  350. </view>
  351. </wd-overlay>
  352. <wd-overlay :show="showoverlay2 && userMemberInfo.isFirstLogin" @click="showoverlay2 = false">
  353. <view class="mt-280rpx flex items-center justify-center">
  354. <view class="relative h-906rpx w-644rpx flex flex-col items-center justify-center text-center" :style="{ backgroundImage: `url(${StaticUrl}/vip-index-popup.png)`, backgroundSize: 'cover', backgroundPosition: 'center' }">
  355. <view class="absolute top-120rpx w-406rpx border-[1rpx_solid_#FFFFFF] rounded-50rpx border-solid px-30rpx py-8rpx text-center text-24rpx text-#FFF">
  356. 您的会员权益已生效有效期至{{ userMemberInfo.expireTime }}
  357. </view>
  358. <image :src="`${StaticUrl}/vip-index-check.png`" class="absolute top-690rpx h-84rpx w-372rpx" @click="router.push({ name: 'smqjh-user-vip' })" />
  359. <image :src="`${StaticUrl}/vip-index-shopping.png`" class="absolute top-800rpx h-84rpx w-288rpx" @click="router.push({ name: 'xsb-homeTabbar' })" />
  360. </view>
  361. </view>
  362. </wd-overlay>
  363. </view>
  364. </view>
  365. </template>
  366. <style scoped lang="scss">
  367. .page-class {
  368. :deep() {
  369. .wd-divider {
  370. margin: 0 !important;
  371. }
  372. }
  373. .flex-box-item {
  374. background: linear-gradient(180deg, #EBFFB4 0%, #FFFFFF 46%, #FFFFFF 100%);
  375. }
  376. .baoyou {
  377. background: url('https://zswl-shop.oss-cn-chengdu.aliyuncs.com/2025/11/771b8a09633448d8b62c0004a8928054.png') no-repeat;
  378. background-size: contain;
  379. }
  380. .linebg {
  381. background: rgba(0, 0, 0, .3);
  382. }
  383. .transition-height {
  384. transition: height 0.3s ease;
  385. }
  386. }
  387. </style>