菜大王uniapp开发
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1264 lines
32 KiB

<script setup>
import { onHide, onShow } from "@dcloudio/uni-app";
import { nextTick, ref } from "vue";
import customTabBar from "@/components/custom-tab-bar/my-tab-bar.vue";
import keyboard from "@/components/keyboard/keyboard.vue";
// import navigation from "@/components/navigation/navigation.vue";
import navv from "@/components/nav/nav.vue";
import {
addCartApi,
getCartInfoApi,
getProductsApi,
getProductTypesApi,
previewApi,
} from "@/libs/api";
import { sleep, useHeight, useRect, validates } from "@/libs/utils";
import useStore from "@/store";
const store = useStore();
/**
* 购物车商品id列表
*/
// const keys = [];
// const plugin = requirePlugin("WechatSI")
// const manager = plugin.getRecordRecognitionManager()
/**
* 搜索关键字
*/
const keyword = ref("");
/**
* 搜索框的高度
*/
// const searchHeight = ref(0);
/**
* 状态栏高度
*/
// const statusBarHeight = ref(0);
/**
* 屏幕的高度
*/
// const screenHeight = ref(0);
/**
* 各种距离
*/
// const safeHeight = ref({
// screen: 0,
// status: 0,
// menu: 0,
// content: 0,
// });
/**
* 当前标签
*/
const currentTab = ref(0);
/**
* 当前子类标签
*/
const currentType = ref(0);
/**
* 右侧商品列表的高度
*/
const bottomHeight = ref(0);
/**
* 右侧商品列表的滚动高度 FIXME: 无法生效
*/
const scrollTop = ref(0);
/**
* 是否显示购物车小球
*/
const showBall = ref(false);
/**
* 购物车小球的动画
*/
const actionTime = ref(true);
/**
* 购物车小球的动画
*/
const animationY = ref({});
/**
* 购物车小球的X轴动画
*/
const animationX = ref({});
/**
* 购物车小球的Y轴坐标
*/
const testY = ref(0);
/**
* 购物车小球的X轴坐标
*/
const testX = ref(0);
/**
* 顶部展开栏左右偏移量
*/
const navScrollLeft = ref(0);
/**
* 顶部类型数据
*/
const navData = ref([]);
/**
* 展开顶部类型数据
*/
const isShowAll = ref(false);
/**
* 子类型数据
*/
const typeData = ref([]);
/**
* 商品数据
*/
const products = ref([]);
/**
* 购物车商品数量
*/
// const cartCount = ref(0);
/**
* 购物车商品列表
*/
// const cartList = ref([]);
/**
* 购物车商品总价
*/
const totalPrice = ref(0);
/**
* 服务费用
*/
const serviceFee = ref(0);
/**
* 配送费
*/
const shippingFee = ref(0);
/**
* 是否显示购物车
*/
const showCart = ref(false);
/**
* 是否显示弹窗
*/
const showModalStatus = ref(false);
/**
* 判断商品列表滚动到底部是否还有数据
*/
const unLoading = ref(false);
/**
* 判断商品列表有无数据
*/
const showList = ref(true);
/**
* 当前页码
*/
const pageIndex = ref(1);
/**
* 每页显示数量
*/
const pageSize = ref(20);
/**
* 总页数
*/
const pageCount = ref(0);
/**
* 判断是否滚动到了底部
*/
const isBottom = ref(false);
/**
* 下拉刷新状态
*/
const triggered = ref(false);
/**
* 触摸开始时的X坐标
*/
const touchDotX = ref(0);
/**
* 触摸开始时的Y坐标
*/
const touchDotY = ref(0);
/**
* 是否触摸开始
*/
const touchStar = ref(false);
/**
* 右侧商品列表的高度
*/
const rightHeight = ref(0);
/**
* 滚动加载数据时当前商品类型id
*/
const scrollId = ref("");
/**
* 是否在搜索中
*/
const isSearching = ref(false);
/**
* 是否显示清除按钮
*/
const showClear = ref(false);
/**
* 滚动页面的高度
*/
const pageContainerHeight = ref(0);
/**
* 标记是否已获取过购物车(首次加载后设为true)
*/
const hasFetchedCart = ref(false);
/**
* 输入购买数量弹框的值
*/
const inputValue = ref("");
/**
* 是否显示购买数量弹框
*/
const isShowkeyboard = ref(false);
/**
* 搜索商品
*/
function onSearch() {
pageIndex.value = 1;
isSearching.value = true;
isShowAll.value = false;
scrollTop.value = 0;
getProducts("");
}
/**
* 取消搜索
*/
function onCancel() {
isSearching.value = false;
keyword.value = "";
showClear.value = false;
pageIndex.value = 1;
isShowAll.value = false;
scrollTop.value = 0;
getProducts(scrollId.value);
}
function onChangeKeyword(e) {
const value = e.detail.value.replace(/\s+/g, "");
showClear.value = value != "";
if (value != "") {
keyword.value = value;
onSearch();
}
else {
onCancel();
}
}
/**
* 展开顶部类型数据
*/
function onShowAllTypes() {
isShowAll.value = !isShowAll.value;
}
/**
* 点击一级分类,并修改二级分类数据
*/
function onSwitchNav(item, index) {
navScrollLeft.value = (index - 2) * 50;
if (currentTab.value === index)
return;
currentTab.value = index;
currentType.value = 0;
products.value = [];
unLoading.value = false;
showList.value = true;
pageIndex.value = 1;
isShowAll.value = false;
keyword.value = "";
isSearching.value = false;
getLeftTypes(item.id);
}
/**
* TODO: 打开语音搜索
*/
function onOpenRecord() {}
/**
* 点击了二级分类,并修改列表
*/
function onSwitchType(item, index) {
if (currentType.value === index)
return;
currentType.value = index;
products.value = [];
unLoading.value = false;
showList.value = true;
pageIndex.value = 1;
scrollId.value = item.id;
getProducts(scrollId.value);
}
/**
* 获取顶部tab标签列表,对应左侧类别
*/
async function getProductTypes(id, isSearch) {
const res = await getProductTypesApi();
if (res.code === "0") {
navData.value = res.data;
if (id) {
getLeftTypes(id);
res.data.forEach((item, index) => {
if (item.id === id) {
currentTab.value = index;
navScrollLeft.value = (index - 2) * 50;
}
});
}
else {
const idx = isSearch ? 0 : currentTab.value;
getLeftTypes(navData.value[idx].id, isSearch ? true : undefined);
}
}
}
/**
* 获取左侧子类别
* @param parentId
* @param isSearch
*/
async function getLeftTypes(parentId, isSearch) {
const res = await getProductTypesApi({ parentId });
if (res.code !== "0") {
return;
}
typeData.value = res.data;
if (res.total > 0) {
scrollId.value = typeData.value[currentType.value].id;
getProducts(isSearch ? "" : scrollId.value);
}
}
/**
* 获取商品信息
*/
async function getProducts(parentId, tips) {
if (!hasFetchedCart.value) {
const params = {
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
};
const res = await getCartInfoApi(params);
store.changeCartList(res.code === "0" ? res.data : []);
// app.globalData.cartList = res.code === "0" ? res.data : [];
hasFetchedCart.value = res.code === "0";
}
loadProductList(parentId, tips);
}
/**
* 菜品列表 全局只加载一次
*/
async function loadProductList(parentId, tips) {
showList.value = true;
// const params = {
// warehouseId: wx.getStorageSync("warehousId"),
// addrId: wx.getStorageSync("addressId"),
// };
// const cartList = store.cartList;
// console.log(store.cartList, 3333);
const total = store.getCartTotalQuantity();
store.increment(total);
const params = {
typeId: parentId,
promotion: false,
orderByField: "name",
ase: true,
search: keyword.value,
pageNum: pageIndex.value,
pageSize: pageSize.value,
warehouseid: uni.getStorageSync("warehousId"),
};
const res = await getProductsApi(params);
if (res.code !== "0")
return;
pageCount.value = res.pageCount;
if (!(res.total > 0)) {
showList.value = false;
return;
}
// 初始化购物车映射表(格式:specId_price -> quantity)
const cartMap = store.getCartMap();
res.data.forEach((item) => {
item.specs.forEach((specsItem) => {
// 为每个规格项生成相同的组合键
const specKey = `${specsItem.id}_${specsItem.price}`;
// 从映射表中获取数量(不存在则设为0)
specsItem.sum = cartMap[specKey] || 0;
});
// 判断是否显示“选规格”按钮
item.showChoose = item.specs.length > 1 ? 1 : 0;
item.showChild = item.specs.length > 1 ? false : item.showChild;
});
const temp = products.value;
products.value = [];
await sleep(100); // 等待更新数据 scrollTop.value 无效的
products.value = pageIndex.value === 1
? res.data
: [...temp, ...(res.data || [])];
rightHeight.value = ((await useRect("#scroll-page"))?.height || 1) + 1;
if (tips === 1) {
currentType.value -= 1;
}
else if (tips === 2) {
currentType.value += 1;
scrollTop.value = 0;
bottomHeight.value = 0;
}
scrollTop.value = 0;
uni.hideNavigationBarLoading(); // 停止下拉刷新
uni.stopPullDownRefresh();
}
/**
* 滚动事件 判断触底否
* @param {Event} e - 滚动事件参数
*/
function onScroll(e) {
if ((e.detail.scrollHeight - e.detail.scrollTop) <= rightHeight.value) {
isBottom.value = true;
}
else {
if (isBottom.value) {
isBottom.value = false;
}
}
}
/**
* 翻页数据
*/
// function onLoadList() {
// console.log("翻页数据");
// const pageIdx = pageIndex.value + 1;
// if (pageIdx <= pageCount.value) {
// pageIndex.value = pageIdx;
// unLoading.value = false;
// getProducts(scrollId.value);
// }
// else {
// unLoading.value = true;
// }
// }
/**
* 下拉刷新
*/
// function onRefresherRefresh() {
// // console.log("下拉刷新");
// triggered.value = false;
// if (currentType.value != 0) {
// getProducts(typeData.value[currentType.value - 1].id, 1);
// }
// }
/**
* 触摸开始事件
* @param e 触摸事件参数
*/
function onTouchStart(e) {
touchDotX.value = e.touches[0].pageX;
touchDotY.value = e.touches[0].pageY;
touchStar.value = true;
}
/**
* 触摸移动事件
* @param e 触摸事件参数
*/
function onTouchMove(e) {
const touchMoveX = e.touches[0].pageX;
const touchMoveY = e.touches[0].pageY;
if (!touchStar.value) {
return;
}
const moveY = Math.abs(touchMoveY - touchDotY.value);
/**
* 左滑手势:横向滑动距离 ≥ 40 且纵向偏移 < 10,且当前不是最后一个一级分类时,切换到下一个一级分类
*/
const isLeft = touchMoveX - touchDotX.value <= -40
&& moveY < 10
&& (currentTab.value < navData.value.length - 1);
/**
* 右滑手势:横向滑动距离 ≥ 40 且纵向偏移 < 10,且当前不是第一个一级分类时,切换到上一个一级分类
*/
const isRight = touchMoveX - touchDotX.value >= 40
&& moveY < 10
&& (currentTab.value !== 0);
// 左右滑动切换一级分类时,重置当前二级分类为第一个
if (isLeft || isRight) {
currentType.value = 0;
products.value = [];
unLoading.value = false;
showList.value = true;
pageIndex.value = 1;
touchStar.value = false;
currentTab.value = isLeft ? currentTab.value + 1 : currentTab.value - 1;
const navId = navData.value[currentTab.value]?.id;
navScrollLeft.value = (currentTab.value - 2) * 50;
getLeftTypes(navId);
}
if (isBottom.value) {
bottomHeight.value = touchDotY.value > touchMoveY
? bottomHeight.value + 0.2 // 向上
: bottomHeight.value - 0.2; // 往下
}
}
/**
* 触摸结束事件
*/
async function onTouchEnd() {
if (
// 当底部手势滑动距离 ≥ 4 且当前二级分类索引未越界时,触发加载下一二级分类
bottomHeight.value >= 4
&& currentType.value <= typeData.value.length - 1
) {
bottomHeight.value = 0;
if (!isSearching.value) {
await getProducts(typeData.value[currentType.value + 1].id, 2);
}
}
if (
// 当底部手势滑动距离大于 0 且已滚动到底部时,重置手势滑动距离
bottomHeight.value >= 0 && isBottom.value
) {
bottomHeight.value = 0;
}
}
async function onGotoNext() {
await getProducts(typeData.value[currentType.value + 1].id, 2);
scrollTop.value = 0;
// if (currentType.value === typeData.value.length - 1) {
// return;
// }
// currentType.value += 1;
// scrollTop.value = 0;
// bottomHeight.value = 0;
}
function onGotoDetail(item) {
uni.navigateTo({
url: `/pages/allDish/dishDetail?id=${item.id}`,
fail(err) {
console.log(err, 333);
},
success(res) {
console.log(res, 222);
},
complete() {
console.log("跳转111");
},
});
}
/**
* 创建购物车小球的动画
*/
async function createAnimation(eX, eY) {
actionTime.value = false;
testX.value = eX;
testY.value = eY;
const bottomX = (store.tabbarItemWidth || 83) * 2 - 30;
const bottomY = uni.getWindowInfo().windowHeight;
const stepX = flyX(bottomX, eX);
const stepY = flyY(bottomY, eY);
showBall.value = true;
animationX.value = stepX.export(); // 创建小球水平动画
animationY.value = stepY.export(); // 创建小球垂直动画
await sleep(400);
actionTime.value = true;
showBall.value = false;
animationX.value = flyX(0, 0).export();
animationY.value = flyY(0, 0).export();
// await sleep(800);
}
/**
* 购物车小球水平移动动画
*/
function flyX(bottomX, ballX, duration = 400) {
const animation = uni.createAnimation({
duration,
timingFunction: "linear",
});
animation.translateX(-bottomX).step();
return animation;
}
/**
* 购物车小球垂直移动动画
*/
function flyY(bottomY, ballY, duration = 400) {
const animation = uni.createAnimation({
duration,
timingFunction: "ease-in",
});
animation.translateY(bottomY - ballY).step();
return animation;
}
/**
* 初始化购物车信息
*/
async function initCartInfo() {
const data = {
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
};
const res = await getCartInfoApi(data);
if (res.code !== "0")
return;
// cartCount.value = res.total;
// cartList.value = res.data || [];
store.changeCartList(res.data);
totalPrice.value = res.data.reduce((acc, item) => acc + item.amount, 0).toFixed(2);
if (store.cartList.length > 0) {
preview(store.cartList.map(item => item.id));
}
else if (showCart.value) {
showCart.value = false;
}
}
/**
* 订单预览
* @param itemIds 商品id列表
*/
async function preview(itemIds) {
const data = {
itemIds: itemIds.join(","),
addrId: uni.getStorageSync("addressId"),
};
const res = await previewApi(data);
serviceFee.value = res.data.serviceFee;
shippingFee.value = res.data.shippingFee;
totalPrice.value = res.data.itemAmount;
}
/**
* 加入购物车
* @param item 商品项
*/
async function onAdd(item, e) {
// item.specs[0].sum = 9;
// if (item.sum === "") {
// item.sum = inputValue.value;
// }
if (!actionTime.value) {
return;
}
createAnimation(e.detail.x, e.detail.y);
const isPass = validates([
() => item.stock == item.sum && "采购数量不能大于库存数量",
() => item.stock == 0 && "库存数量为0无法添加",
]);
if (!isPass) {
return;
}
// 判空为 0, 否则转换为数字
item.sum = Number(item.sum) || 0;
// 起订量(item.minNum), 否则每次+1
const diff = item.sum === 0 ? (item.minNum || 1) : 1;
item.sum += diff;
// 保持输入框与购物车数量同步
inputValue.value = item.sum;
toCart(item, diff);
}
/**
* 更新购物车
* @param item 商品项
* @param diff 变化量
*/
async function toCart(item, diff) {
const data = {
quantity: diff,
specId: item.id,
Chuxiao: item.chuxiao,
isChuxiao: false,
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
// isChuxiao: item.chuxiao,
};
if (!data.specId) {
uni.showModal({
title: "提示",
content: "当前商品规格错误,请稍候再试",
showCancel: false,
confirmText: "确定",
});
}
if (!data.warehouseId || !data.addrId) {
uni.showModal({
title: "提示",
content: "请先选择收货地址,再添加商品",
showCancel: false,
confirmText: "确定",
});
}
// keys.push(item.id);
const res = await addCartApi(data);
// keys.splice(item.id, 1);
if (res.code !== "0") {
return;
}
store.changeCartList(res.data.items);
// initCartInfo();
}
/**
* 减少购买数量
* @param item 商品项
*/
function onMinus(item) {
// if (item.sum === "") {
// item.sum = inputValue.value;
// }
const isPass = validates([
() => item.stock == item.sum && "采购数量不能大于库存数量",
() => item.stock == 0 && "库存数量为0无法添加",
() => item.sum < 0 && "显示错误,采购数量不能小于0",
]);
if (!isPass) {
return;
}
// 判空为 0, 否则转换为数字
item.sum = Number(item.sum) || 0;
const minNum = item.minNum || 1;
// 达到起订量(item.minNum)直接清空, 否则每次-1
const diff = -(item.sum === minNum ? minNum : 1);
item.sum += diff;
// 保持输入框与购物车数量同步
inputValue.value = item.sum;
toCart(item, diff);
}
function onChooseNorm(item) {
item.showChild = !item.showChild;
}
// function onModelConfirm() { }
// function onModelCancel() { }
function openKeyBoard(item) {
isShowkeyboard.value = true;
store.cache.keyboardConfirm = (value) => {
determine(value, item);
};
}
/**
* 确定购买数量
* @param value 购买数量
* @param item 商品项
*/
async function determine(value, item) {
const isPass = validates([
() => item.stock != -1 && value > item.stock && "采购数量不能大于库存数量",
() => item.stock == 0 && "库存数量为0无法添加",
]);
if (!isPass) {
return;
}
item.sum = value;
isShowkeyboard.value = false;
const data = {
quantity: value,
specId: item.id,
Chuxiao: item.chuxiao,
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
isUpdate: 1,
isChuxiao: false,
};
if (!data.specId) {
uni.showModal({
title: "提示",
content: "当前商品规格错误,请稍候再试",
showCancel: false,
confirmText: "确定",
});
}
if (!data.warehouseId || !data.addrId) {
uni.showModal({
title: "提示",
content: "请先选择收货地址,再添加商品",
showCancel: false,
confirmText: "确定",
});
}
const res = await addCartApi(data);
if (res.code !== "0") {
return;
}
// store.changeCartList(res.data);
await initCartInfo();
}
onShow(() => {
if (store.productTypeId) {
currentType.value = 0;
}
showModalStatus.value = false;
showCart.value = false;
// cartList.value = [];
if (store.searchValue) {
onChangeKeyword({ detail: { value: store.searchValue } });
store.searchValue = "";
getProductTypes(store.productTypeId, true);
}
else {
getProductTypes(store.productTypeId);
}
if (store.showVoice) {
onOpenRecord();
store.showVoice = false;
}
nextTick(async () => {
const boxHeight = (await useRect(".first-box"))?.height || 0;
const { content, tabbar } = useHeight();
pageContainerHeight.value = content - boxHeight - tabbar;
});
});
// onLoad(async () => {
// const windowInfo = uni.getWindowInfo();
// tabbarHeight.value = 55 + (windowInfo.screenHeight - windowInfo.safeArea.bottom);
// screenHeight.value = windowInfo.screenHeight;
// tabbarItemWidth.value = store.tabbarItemWidth;
// const res = await useRect(".first-box");
// firstTypeHeight.value = res.height;
// console.log(res, "333");
// });
onHide(() => {
store.productTypeId = "";
isSearching.value = false;
keyword.value = "";
});
</script>
<template>
<navv>
<template #default="{ menu, status }">
<view
class="header-box"
:style="{ paddingTop: `${status}px` }"
>
<view
class="box"
:style="{
height: `${menu || 45}px`,
width: menu ? '70%' : 'auto',
}"
>
<text class="iconfont icon-search1" />
<input
class="input"
type="text"
placeholder="请输入商品名称"
placeholder-style="color: #999999"
:value="keyword"
@onConfirm="onSearch"
@input="onChangeKeyword"
>
<text class="iconfont icon-yuyin" @tap="onOpenRecord" />
</view>
<!-- 横向的分类 一级分类 -->
<view class="first-box">
<view class="left">
<scroll-view
class="scroll-view"
scroll-x
scroll-with-animation
:scroll-left="navScrollLeft"
>
<view
v-for="(navItem, idx) in navData"
:key="idx"
class="list-box"
@tap="() => onSwitchNav(navItem, idx)"
>
<view class="type-list">
<image class="image" :src="navItem.imageUrl" mode="" />
<text
class="name" :class="[currentTab === idx ? 'name-active' : ''] "
>
{{ navItem.name }}
</text>
</view>
</view>
</scroll-view>
</view>
<view class="right" @tap="onShowAllTypes">
<text class="text">
</text>
<text class="text">
</text>
<text class="iconfont icon-down" />
</view>
</view>
</view>
<!-- 内容 可滚动 -->
<view
class="page-container"
:style="{ height: `${pageContainerHeight}px` }"
>
<view v-if="!isSearching" class="left">
<view
v-for="(typeItem, typex) in typeData"
:key="typex"
class="text"
@tap="() => onSwitchType(typeItem, typex)"
>
<text
class="name"
:class="[currentType == typex ? 'text-active' : '']"
>
{{ typeItem.name }}
</text>
</view>
</view>
<!--
:scroll-top="scrollTop" 设置滚动条位置
scroll-y 允许纵向滚动
scroll-with-animation 滚动时带动画
show-scrollbar 显示滚动条
enhanced 启用增强特性
enable-passive 启用 passive 滚动,提升性能
refresher-enabled 启用下拉刷新
refresher-default-style="white" 下拉刷新默认样式为白色
:refresher-threshold="20" 下拉刷新触发阈值 20px
:refresher-triggered="triggered" 控制下拉刷新状态
:throttle="false" 关闭滚动节流
@scrolltolower="onLoadList" 滚动到底部时触发加载下一页
@scroll="onScroll" 滚动过程中实时监听滚动位置
@refresherrefresh="onRefresherrefresh" 下拉刷新时触发重新加载当前分类数据
-->
<scroll-view
id="scroll-page"
class="right"
:scroll-top="scrollTop"
scroll-y
scroll-with-animation
show-scrollbar
enhanced
enable-passive
refresher-enabled
refresher-default-style="white"
:refresher-threshold="20"
:refresher-triggered="triggered"
:refresherrestore="triggered"
:throttle="false"
:style="{
width: isSearching ? '100%' : '80%',
height: '100%',
marginTop: `${-(bottomHeight)}%`,
transition: '.01s all',
}"
@scrolltolower="() => {
// FIXME: onLoadList 原版如何触发
// onLoadList()
}"
@scroll="onScroll"
@refresherrefresh="() => {
// FIXME: onRefresherRefresh 原版如何触发
// onRefresherRefresh()
}"
>
<view
v-if="showList"
class="content-right"
@touchstart="onTouchStart"
@touchmove="onTouchMove"
@touchend="onTouchEnd"
>
<view
v-for="(item, idx) in products"
:key="idx"
class="right-list"
>
<view v-if="!item.showChoose && item.specs[0].stock == 0" class="of-stock" />
<view class="right-list-top">
<view
class="right-list-left"
@tap="() => onGotoDetail(item)"
>
<image class="image" :src="item.imageUrl" mode="" />
<view
v-if="!item.showChoose && item.specs[0].stock == 0"
class="of-stock-text"
>
补货中
</view>
</view>
<view class="right-list-right">
<view class="top" @tap="() => onGotoDetail(item)">
<view class="name">
{{ item.name }}
</view>
<view class="inventory">
{{
// 仅当商品只有1个规格且库存不为“无限库存”(-1)时才显示库存数量
item.specs.length == 1 && !(item.specs[0].stock == -1)
? `库存:${item.specs[0].stock}`
: ''
}}
</view>
</view>
<view class="under">
<view class="price-box" @tap="() => onGotoDetail(item)">
<view class="price">
<text>
<text class="moneySymbol">
</text>{{ item.specs[0].price }}
</text>
</view>
<text v-if="item.specs[0].chuxiao" class="original">
正价:<text class="moneySymbol">
</text>{{ item.specs[0].oldPrice }}/{{ item.specs[0].unit }}
</text>
<text v-else class="no-original">
/{{ item.specs[0].unit }}
</text>
</view>
<view v-if="!item.showChoose && item.specs[0].stock != 0" class="choose-box">
<block v-if="item.specs[0].sum !== 0">
<view class="line-one" />
<view class="line-two" />
<view class="minus" @tap.stop="() => onMinus(item.specs[0])">
<image class="icon" src="/static/home/minus.png" mode="" />
</view>
<text
class="input"
@tap="() => openKeyBoard(item.specs[0])"
>
{{ item.specs[0].sum }}
</text>
</block>
<view class="add" @tap.stop="(e) => onAdd(item.specs[0], e)">
<image class="icon" src="/static/home/add.png" mode="" />
</view>
</view>
<view
v-if="item.showChoose"
class="specifications"
@tap.stop="() => onChooseNorm(item)"
>
{{ item.showChild ? '收起' : '选规格' }}
</view>
</view>
</view>
</view>
<view v-if="item.showChild" class="right-list-under">
<view
v-for="(childs) in item.specs"
:key="childs.id"
class="goods-under-list"
>
<view class="price-box">
<view class="price">
<text class="moneySymbol">
</text>
<text>{{ childs.price }}</text>
</view>
<text v-if="item.specs[0].chuxiao" class="original">
/{{ childs.unit }}
</text>
<text v-else class="no-original">
/{{ childs.unit }}
</text>
<view class="no-original">
{{ childs.stock == -1 ? '' : `库存:${childs.stock}` }}
</view>
</view>
<view class="choose-box">
<block v-if="childs.sum !== 0 || childs.sum != ''">
<view class="line-one" />
<view class="line-two" />
<view
class="minus"
data-quantity="-1"
data-exa="sum"
@tap="() => onMinus(childs)"
>
<image class="icon" src="/static/home/minus.png" mode="" />
</view>
<!-- <text
class="input"
@tap="() => showKeyboard()"
>
{{ childs.sum }}
</text> -->
<text
class="input"
@tap="() => openKeyBoard(childs)"
>
{{ childs.sum }}
</text>
</block>
<view
v-if="childs.stock != 0"
class="add"
data-quantity="1"
data-id="{{childs.id}}"
data-chuxiao="{{childs.chuxiao}}"
data-exa="sum"
@tap="(e) => onAdd(childs, e)"
>
<image class="icon" src="/static/home/add.png" mode="" />
</view>
<text v-if="childs.stock == 0" class="no-stock">
补货中
</text>
</view>
</view>
</view>
</view>
<view
v-if="!isSearching
&& products.length !== 0
&& currentType != typeData.length - 1"
class="next"
@tap="onGotoNext"
>
<text>上划或点击进入</text>
<text style="color: #3aa24b;">
{{ typeData[currentType + 1].name }}
</text>
</view>
</view>
<view
v-if="products.length === 0"
:style="{
fontSize: '29rpx',
color: '#666666',
textAlign: 'center',
marginTop: '30rpx',
}"
>
暂无商品~
</view>
</scroll-view>
</view>
<!-- 遮罩层 -->
<view v-show="isShowAll" class="first-type-mask" @tap="onShowAllTypes" />
<!-- 展开全部分类 -->
<view>
<view
class="first-big-type"
:style="{
top: isShowAll
? `${status + (menu || 45) + 5}px`
: '-1600rpx',
}"
>
<view class="title">
全部分类
</view>
<view class="list-box">
<view
v-for="(navItem, idx) in navData"
:key="idx"
class="listx"
@tap="() => onSwitchNav(navItem, idx)"
>
<image
class="img"
:class="[currentTab == idx ? 'nav-item-img-active' : '']"
:src="navItem.imageUrl"
/>
<view
class="name"
:class="[currentTab == idx ? 'active' : '']"
>
{{ navItem.name }}
</view>
</view>
</view>
<view
class="retract"
@tap="onShowAllTypes"
>
<view class="left">
点击收起
</view>
<text class="iconfont icon-up1" />
</view>
</view>
</view>
<!-- display: showBall ? '' : 'none' -->
<view
v-if="showBall"
:animation="animationY"
:style="{ position: 'fixed', top: `${testY}px` }"
>
<view
class="round"
:animation="animationX"
:style="{ position: 'fixed', left: `${testX}px` }"
/>
</view>
<keyboard
v-if="isShowkeyboard"
@cancel="() => isShowkeyboard = false"
/>
<!-- @confirm="(val) => determine(val)" -->
<customTabBar tab-index="1" />
</template>
</navv>
</template>
<style lang="scss" scoped>
.moneySymbol {
font-size: $text-xs;
}
@import './allDish.scss';
</style>