Files
pj_h5_cloud/src/pages/tabbar/onlineShop.vue
T
2025-09-17 19:00:55 +08:00

255 lines
7.7 KiB
Vue

<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
:auto="false"
>
<template #top>
<view class="flex justify-between items-center my-1">
<tm-text font-size="40" color="#0779FD" class="font-bold">欢迎选购</tm-text>
<view class="flex justify-center items-center" @tap="changeShop">
<image class="size-40rpx" src="@/static/page/address-blue.svg" />
<tm-text font-size="32" color="#0779FD">{{ state.curMerchant.name }}</tm-text>
<image class="size-30rpx" src="@/static/page/arrow-down-s-fill.svg" />
</view>
</view>
<view class="w-full flex items-center">
<tm-input
class="flex-1"
v-model="state.params.keyword"
type="text"
height="72"
minHeight="72"
fontSize="28"
:showClear="true"
:focus="false"
placeholder="请输入商品名称"
style="border: 4rpx solid #0779fd; border-radius: 14rpx"
:focus-highlight="false"
color="#ECF4F9"
@clear="inputClear"
>
<template v-slot:rightIcon>
<tm-button class="mr-1 px-3 py-26rpx text-30rpx!" size="xs" @click="searchProduct">搜 索</tm-button>
</template>
</tm-input>
<tm-badge bg-color="red" :offset="[8, 4]" :label="cartStore.totalCount">
<view class="flex-col-center size-80rpx" @tap="goCart">
<view class="color-#0094ff! iconfont icon-biaoqianlanicon_gouwuche-xuanzhong" />
<view class="c-#0094ff text-22rpx">购物车</view>
</view>
</tm-badge>
</view>
<scroll-view scroll-x>
<view class="w-full flex my-2">
<view
class="mr-2 sub-text-28 py-1 px-2 rounded-1 bg-#fff border border-solid border-transparent whitespace-nowrap"
:class="{ 'bg-#0779FD22! c-#0779FD! border-#0779FD33!': state.params.categoryId === v.id }"
v-for="(v, i) in state.categaryList"
:key="i"
@tap="changeCategary(v.id)"
>
{{ v.name }}
</view>
</view>
</scroll-view>
</template>
<Waterfall
:list="pageHook.list"
:gutter="10"
:breakpoints="{
1800: { rowPerView: 4 },
1400: { rowPerView: 3 },
975: { rowPerView: 2 },
}"
:hasAroundGutter="false"
backgroundColor="#ffffff00"
:crossOrigin="false"
:animationCancel="false"
>
<template #default="{ item, url, index }">
<view class="card" @click="goDetail(item)">
<LazyImg class="rounded-2" :url="filePath(item.picUrl)" />
<view class="p-16rpx flex-col">
<view class="sub-text-32 show-line">{{ item.productName }}</view>
<view class="second-text-26 flex justify-between">
<view>{{ item.productNature == "2" ? "电子称重商品" : "普通商品" }}</view>
<view>已售 {{ item.salesCount || 0 }}</view>
</view>
<view class="flex-row justify-between items-center">
<view class="second-text-32 c-red!">¥{{ item.minPrice.toFixed(2) }}</view>
</view>
</view>
</view>
</template>
</Waterfall>
<tm-drawer
title="切换超市"
:showClose="true"
:showFooter="true"
size="50%"
v-model:show="state.shopDrawerShow"
:duration="100"
zIndex="1200"
>
<tm-radio-group v-model="state.curMerchantRadioId" direction="column">
<tm-radio
v-for="(item, index) in state.merchantList"
:key="index"
class="w-full flex items-center p-2 rounded-3"
:class="[state.curMerchantRadioId == item.id ? 'bg-#e8e8e8' : '']"
:value="item.id"
>
<template v-slot:label="checked">
<view class="flex items-center">
<image class="size-80rpx rounded-2 mr-2" :src="filePath(item.logoPic)" mode="aspectFill" />
<tm-text font-size="30">{{ item.name }}</tm-text>
</view>
</template>
</tm-radio>
</tm-radio-group>
<template #footer>
<view class="px-20rpx pt-2 flex justify-between">
<tm-button skin="thin" block @click="state.shopDrawerShow = false">取消</tm-button>
&nbsp;&nbsp;
<tm-button block @click="confirmRadioMerchant">确定</tm-button>
</view>
</template>
</tm-drawer>
</z-paging>
</crud-layout>
</template>
<script setup lang="ts">
import { onLoad } from "@dcloudio/uni-app"
import { ref, reactive } from "vue"
import { LazyImg, Waterfall } from "vue-waterfall-plugin-next"
import "vue-waterfall-plugin-next/dist/style.css"
import { isEmpty } from "radash"
import { filePath } from "@@/utils/file"
import { merchantApi, onlineShopApi } from "@@/api"
import { hooks, router } from "@@/index"
import { useCartStore } from "@/sheep/stores/cart"
import treeToList from "@/sheep/utils/tree-to-list"
const cartStore = useCartStore()
const state = reactive<any>({
params: {
merchantId: "",
categoryId: "",
size: 10,
keyword: "",
},
merchantList: [],
curMerchant: {},
categaryList: [],
shopDrawerShow: false,
curMerchantRadioId: "",
})
const pageRef = ref<any>(null)
onLoad(async () => {
const app = getApp()
app._initTabbar()
await getAllMerchant()
await getClassify()
await cartStore.getShopCart()
})
// 获取所有商户
const getAllMerchant = async () => {
uni.showLoading({ title: "加载中...", mask: true })
try {
const { code, data }: any = await merchantApi.page({ current: 1, pagesize: 9999999, type: "3" })
if (code != 0) return uni.showToast({ title: "商户获取失败", icon: "error" })
state.merchantList = data.records.filter((item) => item.name.includes("超市")) ?? []
state.curMerchant = state.merchantList[0] ?? {}
state.params.merchantId = state.curMerchant.id
cartStore.saveShopMerchantId(state.curMerchant.id)
} catch (error) {
state.merchantList = []
state.curMerchant = {}
} finally {
uni.hideLoading()
}
}
// 获取分类
const getClassify = async () => {
if (!state.curMerchant.id) return
const { data } = await onlineShopApi.getSpuCategory()
state.categaryList = treeToList(data) ?? []
state.categaryList.unshift({ id: "", name: "全部分类" })
if (!isEmpty(state.categaryList)) {
state.params.categoryId = state.categaryList[0].id
pageRef.value && pageRef.value.reload(false)
}
}
// 打开切换超市抽屉
const changeShop = () => {
state.curMerchantRadioId = state.curMerchant.id || ""
state.shopDrawerShow = true
}
// 确定切换超市
const confirmRadioMerchant = async () => {
state.curMerchant = state.merchantList.find((item: any) => item.id == state.curMerchantRadioId)
state.shopDrawerShow = false
state.params.merchantId = state.curMerchant.id
cartStore.saveShopMerchantId(state.curMerchant.id)
await cartStore.getShopCart()
pageRef.value && pageRef.value.reload(false)
}
// 点击搜索
const searchProduct = () => {
pageRef.value && pageRef.value.reload(false)
}
// 切换分类
const changeCategary = async (categoryId: string) => {
if (state.params.categoryId == categoryId) return
state.params.categoryId = categoryId
pageRef.value && pageRef.value.reload(false)
}
const inputClear = () => {
pageRef.value && pageRef.value.reload(false)
}
const pageHook = hooks.usePage(pageRef, onlineShopApi.getSpuList, null, "data.records")
const query = (page: number, pagesize: number) => {
pageHook.startPage(page, pagesize, false, state.params)
}
const goDetail = async (v: any) => {
const isLogin = await hooks.useCheckLogin()
if (isLogin) router.jump("/pages/online-shop/goods-detail", { id: v.id })
}
const goCart = async () => {
const isLogin = await hooks.useCheckLogin()
if (isLogin) router.jump("/pages/online-shop/cart")
}
</script>