302 lines
8.1 KiB
Vue
302 lines
8.1 KiB
Vue
<template>
|
||
<view>
|
||
<view class="head-wrapper" :style="{top: BarHeight + 'px'}">
|
||
<view class="head-menu">
|
||
<Left class="iconfont" @click="returns" />
|
||
<Home class="iconfont" @click="goHome" />
|
||
</view>
|
||
</view>
|
||
<!-- 幻灯片 -->
|
||
<nut-swiper
|
||
:init-page="0"
|
||
:pagination-visible="false"
|
||
pagination-color="red"
|
||
auto-play="3000">
|
||
<nut-swiper-item v-for="(itm, idx) in swiperList" :key="idx">
|
||
<img
|
||
style="width: 100%; height: 100%"
|
||
:src="itm"
|
||
:alt="idx.toString()" />
|
||
</nut-swiper-item>
|
||
</nut-swiper>
|
||
<!-- 商家信息 -->
|
||
<view class="infoBox">
|
||
<view class="title text-[#333333]">{{ mer_info.name }}</view>
|
||
<view class="flex items-center justify-between mt-3">
|
||
<nut-rate
|
||
spacing="1"
|
||
active-color="rgba(252, 207, 10, 1)"
|
||
v-model="mer_info.rate" />
|
||
<view class="text-[#9E9E9E] text-[25px]">销量:10000</view>
|
||
<view class="text-[#9E9E9E] text-[25px]"
|
||
>营业时间:{{ mer_info.week_start }}-{{ mer_info.week_end }}</view
|
||
>
|
||
</view>
|
||
<view class="line"></view>
|
||
<view class="bom">
|
||
<view
|
||
class="iconfont icon-dizhi text-[#C4C4C4]"
|
||
style="width: 15px; height: 15px; margin-right: 15px"></view>
|
||
<view class="left">
|
||
<view>{{ mer_info.address || '暂无商家地址' }}</view>
|
||
<view class="sub mt-1"
|
||
>距离您{{
|
||
calculateDistance(
|
||
userLocalNum.t,
|
||
userLocalNum.l,
|
||
Number(mer_info.lat),
|
||
Number(mer_info.lon),
|
||
)
|
||
}}
|
||
</view>
|
||
</view>
|
||
<view class="right">
|
||
<view @click="clickMap">
|
||
<image
|
||
class="w-[50px] h-[50px]"
|
||
src="http://p1.meituan.net/csc/92ee8512c90527169b44e07fd11d250d924.png" />
|
||
</view>
|
||
<view @click="clickPhone">
|
||
<image
|
||
class="w-[50px] h-[50px]"
|
||
src="http://p0.meituan.net/csc/ab0493b124a6bb858bf82a2340767c0d919.png" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- 商品列表 -->
|
||
<view class="good-class" v-if="class_list.length > 0">
|
||
<nut-tabs
|
||
v-model="value"
|
||
title-scroll
|
||
size="large"
|
||
direction="vertical"
|
||
title-gutter="5"
|
||
animated-time="0"
|
||
type=""
|
||
name="tabName">
|
||
<nut-tab-pane
|
||
v-for="(itm, index) in good_list"
|
||
:key="index"
|
||
:title="itm.name"
|
||
:pane-key="index">
|
||
<view v-if="itm.Goods.length > 0">
|
||
<view class="list" v-for="(item, index) in itm.Goods" :key="index">
|
||
<view class="item" @click.stop="toGoodDetails(item.gid, 1)">
|
||
<image :src="item.cover" lazy-load />
|
||
<view class="right">
|
||
<view class="name">{{ item.name }}</view>
|
||
<view class="stock text-[25px]">剩余:{{ item.stock }}</view>
|
||
<view class="bom">
|
||
<view>
|
||
<view class="price">
|
||
<text style="font-size: 15px">{{ item.number }}元</text>
|
||
</view>
|
||
<view class="price">
|
||
<text style="font-size: 15px"
|
||
>{{ item.exchange }}积分</text
|
||
>
|
||
</view>
|
||
</view>
|
||
<view class="flex items-center justify-between">
|
||
<view
|
||
v-if="item.cartNum > 0"
|
||
class="btn"
|
||
@click.stop="add_cart(item, 1)">
|
||
<Minus />
|
||
</view>
|
||
<view v-if="item.cartNum > 0" style="margin: 0 10px">
|
||
{{ item.cartNum }}
|
||
</view>
|
||
<view class="btn" @click.stop="add_cart(item, 2)">
|
||
<Plus />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<nut-empty v-else description="该分类暂无商品"></nut-empty>
|
||
<view style="height: 180rpx"></view>
|
||
</nut-tab-pane>
|
||
</nut-tabs>
|
||
</view>
|
||
<nut-empty v-else description="该商家暂无商品"></nut-empty>
|
||
<!-- 购物车 -->
|
||
<cart ref="cartRef" :mer-info="mer_info" @update-cart="updateCartNum" />
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import Taro from '@tarojs/taro';
|
||
import {Cart2, Left, Home, Uploader, Plus, Minus} from '@nutui/icons-vue-taro';
|
||
import {Ref, ref} from 'vue';
|
||
import {calculateDistance} from '@/utils';
|
||
import {getGoodList, getMerCategory} from '@/api/goods';
|
||
import Cart from '@/components/Cart.vue';
|
||
|
||
const statusBarHeight = Taro.getSystemInfoSync()?.statusBarHeight;
|
||
const BarHeight = ref((statusBarHeight as number) + 6);
|
||
|
||
const swiperList = ref([]);
|
||
|
||
const mer_info = ref<any>({});
|
||
|
||
const value = ref('0');
|
||
|
||
const userLocalNum = ref({
|
||
l: 0,
|
||
t: 0,
|
||
});
|
||
|
||
Taro.useLoad(async () => {
|
||
Taro.getLocation({
|
||
type: 'wgs84',
|
||
success: res => {
|
||
userLocalNum.value.l = res.longitude;
|
||
userLocalNum.value.t = res.latitude;
|
||
},
|
||
});
|
||
mer_info.value = Taro.getStorageSync('mer_info');
|
||
Taro.setNavigationBarTitle({
|
||
title: mer_info.value.name,
|
||
});
|
||
swiperList.value = mer_info.value.img.split(',');
|
||
await get_class_list();
|
||
await cartRef.value.get_cart_list();
|
||
});
|
||
|
||
const clickPhone = () => {
|
||
Taro.makePhoneCall({
|
||
phoneNumber: mer_info.value.mobile,
|
||
});
|
||
};
|
||
|
||
const clickMap = () => {
|
||
Taro.openLocation({
|
||
name: mer_info.value.name,
|
||
address: mer_info.value.address,
|
||
latitude: Number(mer_info.value.lat),
|
||
longitude: Number(mer_info.value.lon),
|
||
scale: 18,
|
||
});
|
||
};
|
||
|
||
const class_list = ref<
|
||
Array<{
|
||
ID?: number;
|
||
name?: string;
|
||
}>
|
||
>([]);
|
||
const get_class_list = async () => {
|
||
const res = await getMerCategory({
|
||
Bid: mer_info.value.bid,
|
||
});
|
||
class_list.value = res.data.data || [];
|
||
await get_good_list(class_list.value[0].ID as number);
|
||
};
|
||
|
||
// const clickTab = (val: any) => {
|
||
// get_good_list(class_list.value[val.paneKey].ID as number);
|
||
// };
|
||
|
||
interface goodList {
|
||
ID: number;
|
||
name: string;
|
||
bid: string;
|
||
Goods: GoodsType[];
|
||
}
|
||
|
||
interface GoodsType {
|
||
gid: string;
|
||
cover: string;
|
||
name: string;
|
||
number: number;
|
||
stock: number;
|
||
cartNum: number;
|
||
exchange: number;
|
||
}
|
||
|
||
interface CartItems {
|
||
bid: string;
|
||
gid: string;
|
||
number: number;
|
||
price: number;
|
||
cover: string;
|
||
name: string;
|
||
exchange: number;
|
||
}
|
||
|
||
const good_list = ref<goodList[]>([]);
|
||
const get_good_list = async (id: number) => {
|
||
Taro.showLoading({
|
||
title: '加载中',
|
||
mask: true,
|
||
});
|
||
const res = await getGoodList({
|
||
bid: mer_info.value.bid,
|
||
goods_class_id: id,
|
||
status: 1,
|
||
state: 1,
|
||
});
|
||
good_list.value = res.data.data || [];
|
||
Taro.hideLoading();
|
||
};
|
||
|
||
const toGoodDetails = (id: string, type: number) => {
|
||
Taro.navigateTo({
|
||
url: `/pages/goods/goods_detail/index?gid=${id}&type=${type}`,
|
||
});
|
||
};
|
||
|
||
const cartRef = ref(null) as Ref;
|
||
|
||
const add_cart = (item: GoodsType, type: number) => {
|
||
let num = 0;
|
||
if (type === 1) {
|
||
num = Number(item.cartNum) - 1;
|
||
} else {
|
||
num = item.cartNum ? Number(item.cartNum) + 1 : 1;
|
||
}
|
||
|
||
cartRef.value.add_cart(item, num);
|
||
};
|
||
|
||
const updateCartNum = (cartItems: CartItems[]) => {
|
||
if (cartItems.length > 0) {
|
||
good_list.value.forEach((category: goodList) => {
|
||
category.Goods.forEach((good: GoodsType) => {
|
||
cartItems.forEach((cartItem: CartItems) => {
|
||
if (good.gid === cartItem.gid) {
|
||
good.cartNum = cartItem.number;
|
||
}
|
||
});
|
||
});
|
||
});
|
||
} else {
|
||
good_list.value.forEach((category: goodList) => {
|
||
category.Goods.forEach((good: GoodsType) => {
|
||
Reflect.deleteProperty(good, 'cartNum');
|
||
});
|
||
});
|
||
}
|
||
};
|
||
|
||
const returns = () => {
|
||
Taro.navigateBack({
|
||
delta: 1,
|
||
});
|
||
};
|
||
|
||
const goHome = () => {
|
||
Taro.switchTab({
|
||
url: '/pages/index/index',
|
||
});
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
@import './index.scss';
|
||
</style>
|