feat:共富商城购物车
This commit is contained in:
1 parent
a2ecdbc187
commit
467dcc637d
20 files changed
+429
-122
No files matched your search
@@ -20,15 +20,15 @@ VITE_OAUTH2_APP_CLIENT='mini:mini'
|
||||
# VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
|
||||
#VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
|
||||
# VITE_APP_DEV_SERVICE = http://192.168.101.174:9999 # 邓-本地
|
||||
VITE_APP_DEV_SERVICE = http://127.0.0.1:9999 # 邓-本地
|
||||
; VITE_APP_DEV_SERVICE = http://123.157.250.162:8089/api # 测试线上
|
||||
# VITE_APP_DEV_SERVICE = http://127.0.0.1:9999 # 邓-本地
|
||||
VITE_APP_DEV_SERVICE = http://123.157.250.162:8089/api # 测试线上
|
||||
|
||||
# --------------------------- 开发环境 图片访问基础地址 ---------------------------
|
||||
# VITE_IMAGE_DEV_PATH = https://stgl.pj.gov.cn/api # 域名线上
|
||||
#VITE_IMAGE_DEV_PATH = http://59.202.170.152:81/api # 信创线上
|
||||
# VITE_IMAGE_DEV_PATH = http://192.168.101.174:9999 # 邓-本地
|
||||
VITE_IMAGE_DEV_PATH = http://127.0.0.1:9999
|
||||
; VITE_IMAGE_DEV_PATH = http://123.157.250.162:8089/api # 测试线上
|
||||
# VITE_IMAGE_DEV_PATH = http://127.0.0.1:9999
|
||||
VITE_IMAGE_DEV_PATH = http://123.157.250.162:8089/api # 测试线上
|
||||
|
||||
# --------------------------- 生产环境 api地址 ----------------------------------
|
||||
VITE_APP_PROD_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
|
||||
|
||||
@@ -198,6 +198,13 @@
|
||||
"navigationBarTitleText": "商品分类管理",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "goods-cart",
|
||||
"style": {
|
||||
"navigationBarTitleText": "购物车",
|
||||
"disableScroll": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -55,7 +55,7 @@ const getDetail = async () => {
|
||||
|
||||
// 获取购物车信息
|
||||
const getFoodCart = async () => {
|
||||
const { data } = await foodApi.getShopCar({ merchantId: state.detailId, hardType: "CANTEEN" })
|
||||
const { data } = await orderApi.getShopCar({ merchantId: state.detailId, hardType: "CANTEEN" })
|
||||
state.cartList = data ?? []
|
||||
if (isEmpty(state.cartList)) {
|
||||
state.foodList.forEach((v: any) => {
|
||||
@@ -154,7 +154,7 @@ const updateFoodCart = async () => {
|
||||
})
|
||||
if (isEmpty(list)) return
|
||||
const _pa = { merchantId: state.detailId, list: list, hardType: "CANTEEN" }
|
||||
const { data, code }: any = await foodApi.updateShopCar(_pa)
|
||||
const { data, code }: any = await orderApi.updateShopCar(_pa)
|
||||
if (code == 0) await getFoodCart()
|
||||
}
|
||||
|
||||
|
||||
@@ -4,15 +4,9 @@
|
||||
<tm-sheet :margin="[0]">
|
||||
<tm-alert :border="['2']" :borderColor="['#89c0ff']" :darkBorderColor="['#3b5066']">访客邀约请填写以下信息</tm-alert>
|
||||
<tm-form @submit="onsubmit" v-model="form" :rules="rules" direction="vertical">
|
||||
<!-- <tm-form-item name="name" label="访客姓名">
|
||||
<tm-input color="transparent" v-model.trim="form.name" placeholder="请输入真实姓名" />
|
||||
</tm-form-item> -->
|
||||
<tm-form-item name="mobile" label="访客手机号">
|
||||
<tm-input color="transparent" v-model.trim="form.mobile" placeholder="请输入访客手机号" />
|
||||
</tm-form-item>
|
||||
<!-- <tm-form-item name="companyName" label="来访公司名称">
|
||||
<tm-input color="transparent" v-model.trim="form.companyName" placeholder="来访公司名称" />
|
||||
</tm-form-item> -->
|
||||
<tm-form-item name="vStartDate" label="拜访开始时间 >" @click="startDatePicker('vStartDate')">
|
||||
<template #label>
|
||||
<span>拜访开始时间 </span>
|
||||
@@ -39,30 +33,6 @@
|
||||
color="transparent"
|
||||
/>
|
||||
</tm-form-item>
|
||||
|
||||
<!-- <tm-form-item name="deptId" label="拜访部门">
|
||||
<tm-drawer :show-close="true" :show-footer="true" size="auto" title="请选择拜访部门">
|
||||
<template #trigger>
|
||||
<tm-input :modelValue="form.deptId" placeholder="请选择拜访部门" style="pointer-events: none" disabled color="transparent">
|
||||
<template v-slot:rightIcon>
|
||||
<tm-icon name="arrow-right-s-line"></tm-icon>
|
||||
</template>
|
||||
</tm-input>
|
||||
</template>
|
||||
<tm-text color="#999999"></tm-text>
|
||||
</tm-drawer>
|
||||
</tm-form-item> -->
|
||||
|
||||
<!-- <tm-form-item name="reasonValue" label="拜访原因">
|
||||
<tm-picker @confirm="reasonPickerConfirm" :list="visitorReasonList">
|
||||
<tm-input :modelValue="form.reasonText" placeholder="请选择拜访原因" style="pointer-events: none" disabled color="transparent">
|
||||
<template #rightIcon>
|
||||
<tm-icon name="arrow-right-s-line"></tm-icon>
|
||||
</template>
|
||||
</tm-input>
|
||||
</tm-picker>
|
||||
</tm-form-item> -->
|
||||
|
||||
<tm-form-item name="isOtherPeople" label="是否可随行人员" direction="horizontal" labelWidth="500">
|
||||
<tm-switch v-model="form.isOtherPeople" />
|
||||
</tm-form-item>
|
||||
@@ -133,49 +103,20 @@ interface FormData {
|
||||
}
|
||||
|
||||
const form = reactive<FormData>({
|
||||
// name: "",
|
||||
mobile: "",
|
||||
// companyName: "",
|
||||
vStartDate: "",
|
||||
vEndDate: "",
|
||||
// reasonValue: "",
|
||||
// reasonText: "",
|
||||
isOtherPeople: true,
|
||||
isDrive: true,
|
||||
})
|
||||
const showDatePicker = ref(false)
|
||||
const curDateType = ref("")
|
||||
const confirmModalShow = ref(false)
|
||||
// const visitorReasonList = ref<{ title: string; id: string }[]>([])
|
||||
|
||||
// onLoad(() => {
|
||||
// getVisitorReasonList()
|
||||
// })
|
||||
|
||||
// 获取拜访原因列表
|
||||
// const getVisitorReasonList = async () => {
|
||||
// const { code, data } = await invitationApi.getDictListByType("1")
|
||||
// if (code == 0 && data) {
|
||||
// visitorReasonList.value = data.map((item: any) => ({ title: item.label, id: item.value }))
|
||||
// return
|
||||
// }
|
||||
// visitorReasonList.value = []
|
||||
// }
|
||||
|
||||
// 来访原因选择器确认
|
||||
// const reasonPickerConfirm = (ids: string) => {
|
||||
// const reason = visitorReasonList.value.find((item) => item.id === ids[0])
|
||||
// form.reasonText = reason?.title || ""
|
||||
// form.reasonValue = reason?.id || ""
|
||||
// }
|
||||
|
||||
const rules: Record<string, TM.FORM_RULE[]> = {
|
||||
// name: [{ required: true, message: "姓名2到5个字符", rule: /^.{2,5}$/ }],
|
||||
mobile: [{ required: true, message: "请输入正确的手机号", rule: /^(?:(?:\+|00)86)?1\d{10}$/ }],
|
||||
// companyName: [{ required: true, message: "请输入来访公司名称" }],
|
||||
vStartDate: [{ required: true, message: "请选择拜访开始时间" }],
|
||||
vEndDate: [{ required: true, message: "请选择拜访离开时间" }],
|
||||
// reasonValue: [{ required: true, message: "请选择拜访原因" }],
|
||||
}
|
||||
|
||||
// 开始日期选择
|
||||
@@ -237,13 +178,9 @@ const confirmSubmit = async () => {
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
Object.assign(form, {
|
||||
// name: "",
|
||||
mobile: "",
|
||||
// companyName: "",
|
||||
vstartDate: "",
|
||||
vendDate: "",
|
||||
// reasonValue: "",
|
||||
// reasonText: "",
|
||||
isOtherPeople: true,
|
||||
isDrive: true,
|
||||
})
|
||||
|
||||
@@ -138,7 +138,7 @@ import { reactive, nextTick } from "vue"
|
||||
import { onLoad, onShow } from "@dcloudio/uni-app"
|
||||
import { isEmpty } from "radash"
|
||||
import { hooks, router } from "@@/index"
|
||||
import { foodApi, merchantApi, payApi, shopApi } from "@@/api"
|
||||
import { foodApi, merchantApi, orderApi, payApi, shopApi } from "@@/api"
|
||||
import { filePath } from "@@/utils/file"
|
||||
// import ProductRow from "./components/product-row.vue"
|
||||
// import ProductCart from "./components/product-cart.vue"
|
||||
@@ -196,7 +196,7 @@ const getDetail = async () => {
|
||||
}
|
||||
|
||||
const getShopCart = async () => {
|
||||
const { data } = await foodApi.getShopCar({ merchantId: state.merchantId, hardType: "SUPERMARKET" })
|
||||
const { data } = await orderApi.getShopCar({ merchantId: state.merchantId, hardType: "SUPERMARKET" })
|
||||
state.cartList = data ?? []
|
||||
state.totPrice = state.cartList.map((v) => Number(v.totalPrice)).reduce((pre, next) => pre + next, 0)
|
||||
state.totCount = state.cartList.map((v) => v.productCount).reduce((pre, next) => pre + next, 0)
|
||||
@@ -293,7 +293,7 @@ const updateShopCart = async () => {
|
||||
productId: v.productId,
|
||||
}
|
||||
})
|
||||
const { code }: any = await foodApi.updateShopCar({ merchantId: state.merchantId, list, hardType: "SUPERMARKET" })
|
||||
const { code }: any = await orderApi.updateShopCar({ merchantId: state.merchantId, list, hardType: "SUPERMARKET" })
|
||||
if (code == 0) await getShopCart()
|
||||
}
|
||||
|
||||
|
||||
@@ -44,15 +44,17 @@
|
||||
<script setup lang="ts">
|
||||
import ProductTotal from "./components/product-total.vue"
|
||||
import { isEmpty } from "radash"
|
||||
import { useCartStore } from "@/sheep/stores/cart"
|
||||
import { useOnlineCartStore } from "@/sheep/stores/online-cart"
|
||||
import { payApi } from "@/sheep/api"
|
||||
import { hooks, router } from "@/sheep"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
|
||||
const cartStore = useCartStore()
|
||||
const cartStore = useOnlineCartStore()
|
||||
|
||||
// 点击提交订单
|
||||
const doBuy = async () => {
|
||||
if (isEmpty(cartStore.cart)) return uni.showToast({ title: "请至少购买一件商品", icon: "none" })
|
||||
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "是否确定购买",
|
||||
@@ -67,8 +69,6 @@ const doBuy = async () => {
|
||||
// 提交订单
|
||||
const submitPay = async () => {
|
||||
try {
|
||||
if (isEmpty(cartStore.cart)) return uni.showToast({ title: "请至少购买一件商品", icon: "none" })
|
||||
|
||||
uni.showLoading({ title: "支付中...", mask: false })
|
||||
const { code, msg }: any = await payApi.createSupermarketOrder({ carParentId: cartStore.cart[0].parentCarId, hardType: "SUPERMARKET" })
|
||||
if (code != 0) throw new Error(msg)
|
||||
|
||||
@@ -4,11 +4,11 @@ import { onLoad } from "@dcloudio/uni-app"
|
||||
import { onlineShopApi } from "@@/api"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
import ProductSku from "./components/product-sku.vue"
|
||||
import { useCartStore } from "@/sheep/stores/cart"
|
||||
import { useOnlineCartStore } from "@/sheep/stores/online-cart"
|
||||
import { hooks, router } from "@/sheep"
|
||||
import { displayPrice } from "@/sheep/utils/formatMoney"
|
||||
|
||||
const cartStore = useCartStore()
|
||||
const cartStore = useOnlineCartStore()
|
||||
|
||||
const state = reactive<any>({
|
||||
detailId: null,
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<tm-drawer z-index="800" v-model:show="modelValue" showFooter showClose title="加入购物车" size="70%" bgColor="#ECF4F9" @close="doClose">
|
||||
<view class="flex-col card py-20rpx px-30rpx mb-20rpx">
|
||||
<view class="prefix_title mb-15rpx">商品信息</view>
|
||||
<view class="flex items-center">
|
||||
<image
|
||||
class="size-160rpx bg-#eeeeee rounded-1 mr-2"
|
||||
:src="filePath(goodsInfo.coverImage)"
|
||||
mode="aspectFill"
|
||||
@tap.stop="goodsInfo.coverImage && usePreviewImage(filePath(goodsInfo.coverImage))"
|
||||
/>
|
||||
<view class="flex-1 overflow-hidden">
|
||||
<view class="sub-text-32 truncate">{{ goodsInfo.title }}</view>
|
||||
<view class="second-text-32 c-red!">
|
||||
<text>¥{{ displayPrice(state.selectedSku.price, "") || 0 }}</text>
|
||||
<!-- <text class="m-l-20rpx second-text-28 line-through">¥{{ displayPrice(state.selectedSku.retailPrice, "") || 0 }}</text> -->
|
||||
</view>
|
||||
<view class="second-text-26">库存 {{ state.selectedSku.stock || 0 }}</view>
|
||||
<view class="second-text-26">
|
||||
已选择 {{ `${state.selectedSku.skuName || "未选择"} / ${state.selectedSku.weightG + "克"},数量 ${state.goodsCount}` }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 包装单位 -->
|
||||
<view class="flex-col card p-y-20rpx p-x-30rpx mb-20rpx">
|
||||
<view class="prefix_title mb-15rpx">包装单位</view>
|
||||
<view class="flex flex-wrap">
|
||||
<view
|
||||
class="text-center rounded-2 mr-4 mb-2 py-2 px-3 text-28 bg-#F2F2F2 c-black border border-solid border-#E5E5E5"
|
||||
:class="{ 'bg-#0094ff! c-white!': state.selectedSku.id === v.id }"
|
||||
v-for="v in goodsInfo.skuList"
|
||||
:key="v.id"
|
||||
@click="onSelectSku(v)"
|
||||
>
|
||||
{{ v.skuName + " / " + v.weightG + "克" }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 购买数量 -->
|
||||
<view class="flex-col card p-y-20rpx p-x-30rpx mb-20rpx">
|
||||
<view class="prefix_title mb-15rpx">购买数量</view>
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="second-text-28">库存 {{ state.selectedSku.stock }}</view>
|
||||
<view class="flex">
|
||||
<view class="flex-row-center size-40rpx rounded-full border-1px border-solid border-color-#0094ff" @tap.stop="handleNumRemove">
|
||||
<view class="iconfont icon-a--" />
|
||||
</view>
|
||||
<view class="sub-text-28 m-x-20rpx">{{ String(state.goodsCount).padStart(2, "0") }}</view>
|
||||
<view class="flex-row-center size-40rpx rounded-full bg-#0094ff" @tap.stop="handleNumAdd">
|
||||
<view class="font-size-40rpx color-white iconfont icon-a-" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template #footer>
|
||||
<button
|
||||
class="mx-12 rounded-3 bg-#0094ff sub-text-30 py-2 c-white! active:bg-#0094ff99"
|
||||
:class="{ 'bg-#0094ff77!': Object.keys(state.selectedSku).length === 0 }"
|
||||
@tap="handleSkuAddToCart"
|
||||
>
|
||||
加入购物车
|
||||
</button>
|
||||
</template>
|
||||
</tm-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, watch } from "vue"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
import { usePreviewImage } from "@/sheep/hooks/use-img"
|
||||
import { isEmpty } from "radash"
|
||||
import { displayPrice } from "@/sheep/utils/formatMoney"
|
||||
|
||||
const modelValue = defineModel("modelValue", { default: false })
|
||||
const emit = defineEmits<{ (e: "onSkuAddToCart", val: object): void }>()
|
||||
const props = defineProps({
|
||||
goodsInfo: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
})
|
||||
|
||||
const state = reactive<any>({
|
||||
selectedSku: {},
|
||||
goodsCount: 1,
|
||||
})
|
||||
|
||||
watch(modelValue, (newValue) => {
|
||||
if (newValue && !isEmpty(props.goodsInfo)) {
|
||||
state.selectedSku = props.goodsInfo.skuList[0]
|
||||
}
|
||||
})
|
||||
|
||||
// 选择规格/取消选择规格
|
||||
const onSelectSku = (skuItem: any) => {
|
||||
if (state.selectedSku.id == skuItem.id) {
|
||||
state.selectedSku = {}
|
||||
return
|
||||
}
|
||||
state.selectedSku = skuItem
|
||||
}
|
||||
|
||||
// 加数量
|
||||
const handleNumAdd = () => {
|
||||
if (state.goodsCount >= state.selectedSku.stock) return uni.showToast({ title: "库存不足", icon: "none" })
|
||||
state.goodsCount += 1
|
||||
}
|
||||
|
||||
// 减数量
|
||||
const handleNumRemove = () => {
|
||||
if (state.goodsCount <= 1) return
|
||||
state.goodsCount -= 1
|
||||
}
|
||||
|
||||
// 点击sku加入到购物车
|
||||
const handleSkuAddToCart = async () => {
|
||||
if (!state.selectedSku.id) return uni.showToast({ title: "请选择包装单位", icon: "none" })
|
||||
|
||||
// 检查库存
|
||||
// try {
|
||||
// uni.showLoading({ title: "加载中", mask: true })
|
||||
// const { code }: any = await shopApi.checkSpuStock({ spuId: props.goodsInfo.id, incrCount: state.goodsCount })
|
||||
// if (code != 0) return uni.showToast({ title: "库存不足", icon: "none" })
|
||||
// } catch (e) {
|
||||
// console.error(e)
|
||||
// } finally {
|
||||
// uni.hideLoading()
|
||||
// }
|
||||
|
||||
// 检查库存
|
||||
if (props.goodsInfo.stock === 0 || Number(state.goodsCount) > Number(state.selectedSku.stock))
|
||||
return uni.showToast({ title: "库存不足", icon: "none" })
|
||||
|
||||
emit("onSkuAddToCart", {
|
||||
spuId: props.goodsInfo.id,
|
||||
skuId: state.selectedSku.id,
|
||||
productCount: state.goodsCount,
|
||||
...state.selectedSku,
|
||||
})
|
||||
}
|
||||
|
||||
// 关闭
|
||||
const doClose = () => {
|
||||
modelValue.value = false
|
||||
state.selectedSku = {}
|
||||
state.goodsCount = 1
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<view class="flex-row items-center justify-between" @tap="doContainer">
|
||||
<view class="flex-row-center">
|
||||
<view class="flex-row-center size-80rpx rounded-full bg-#0094ff">
|
||||
<view class="color-white! iconfont icon-biaoqianlanicon_gouwuche-xuanzhong" />
|
||||
</view>
|
||||
<view class="flex-col m-l-30rpx">
|
||||
<view class="second-text-36 color-#f63a36!">¥ {{ hooks.useMoney(props.totPrice) }}</view>
|
||||
<view class="sub-text-28">共{{ props.totCount }}件</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bg-#0094ff p-x-30rpx p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap.stop="doBuy">提交订单</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { hooks } from "@@/index"
|
||||
|
||||
const emit = defineEmits(["submit", "doContainer"])
|
||||
|
||||
export type Props = {
|
||||
totPrice: number
|
||||
totCount: number
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
totPrice: 0,
|
||||
totCount: 0,
|
||||
})
|
||||
|
||||
const doBuy = () => emit("submit")
|
||||
|
||||
const doContainer = () => emit("doContainer")
|
||||
</script>
|
||||
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<crud-layout title="购物车" mainIsScroll bg="/static/page/blue-bg.png">
|
||||
<view class="h-20rpx"></view>
|
||||
<view v-if="cartStore.totalCount > 0" class="flex-row card px-15rpx py-25rpx mb-20rpx" v-for="(v, i) in cartStore.cart" :key="i">
|
||||
<image class="size-160rpx rounded-12rpx mr-20rpx bg-#eeeeee" :src="filePath(v.productPic)" mode="aspectFill" />
|
||||
<view class="flex-1 overflow-hidden">
|
||||
<view class="sub-text-30 truncate">{{ v.productName }}</view>
|
||||
<view class="second-text-26 show-line">单位 {{ v.unit }}</view>
|
||||
<view class="flex-row justify-between items-center">
|
||||
<view class="second-text-30"> ¥{{ hooks.useMoney(v.productPrice) }} </view>
|
||||
<view class="second-text-30">x {{ v.productCount }}</view>
|
||||
</view>
|
||||
<view class="flex-row justify-between items-center">
|
||||
<view class="second-text-32 c-red!">¥{{ hooks.useMoney(v.totalPrice) }}</view>
|
||||
<view class="flex-row justify-between items-center">
|
||||
<view
|
||||
class="flex-row-center size-40rpx rounded-full border-1px border-solid border-color-#0094ff"
|
||||
@tap.stop="remove(v.productId)"
|
||||
>
|
||||
<view class="iconfont icon-a--" />
|
||||
</view>
|
||||
<view class="sub-text-28 m-x-20rpx">{{ v.productCount }}</view>
|
||||
<view class="flex-row-center size-40rpx rounded-full bg-#0094ff" @tap.stop="add(v.productId)">
|
||||
<view class="font-size-40rpx color-white iconfont icon-a-" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else class="flex-col justify-center items-center pt-300rpx">
|
||||
<image src="@/static/page/cart_empty.png" class="w-350rpx h-350rpx" />
|
||||
<text class="sub-text-32 font-bold">购物车空空如也</text>
|
||||
</view>
|
||||
|
||||
<template #main-bottom>
|
||||
<view class="z-200 p-x-30rpx p-y-30rpx bg-white">
|
||||
<product-total :totPrice="cartStore.totPrice" :totCount="cartStore.totalCount" @doContainer="" @submit="doBuy" />
|
||||
</view>
|
||||
</template>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ProductTotal from "./components/product-total.vue"
|
||||
import { isEmpty } from "radash"
|
||||
import { useOnlineCartStore } from "@/sheep/stores/online-cart"
|
||||
import { payApi } from "@/sheep/api"
|
||||
import { hooks, router } from "@/sheep"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
|
||||
const cartStore = useOnlineCartStore()
|
||||
|
||||
// 点击提交订单
|
||||
const doBuy = async () => {
|
||||
if (isEmpty(cartStore.cart)) return uni.showToast({ title: "请至少购买一件商品", icon: "none" })
|
||||
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "是否确定购买",
|
||||
confirmColor: "#0094ff",
|
||||
success: async (res) => {
|
||||
if (!res.confirm) return
|
||||
submitPay()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 提交订单
|
||||
const submitPay = async () => {
|
||||
try {
|
||||
uni.showLoading({ title: "支付中...", mask: false })
|
||||
const { code, msg }: any = await payApi.createSupermarketOrder({ carParentId: cartStore.cart[0].parentCarId, hardType: "SUPERMARKET" })
|
||||
if (code != 0) throw new Error(msg)
|
||||
uni.showToast({ title: "支付成功", icon: "none" })
|
||||
router.jump("/pages/tabbar/order")
|
||||
} catch (error: any) {
|
||||
uni.showToast({ title: error.message, icon: "none" })
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
const add = async (productId: string) => {
|
||||
await cartStore.addProductCount(productId)
|
||||
}
|
||||
const remove = async (productId: string) => {
|
||||
await cartStore.removeProductCount(productId)
|
||||
}
|
||||
</script>
|
||||
@@ -49,7 +49,20 @@
|
||||
<view class="mt-20rpx overflow-auto text-26rpx!" v-html="state.detail.description"></view>
|
||||
</view>
|
||||
<view class="h-30rpx" />
|
||||
|
||||
<template #main-bottom>
|
||||
<view class="flex-row justify-between items-center my-4 mx-12">
|
||||
<tm-badge bg-color="red" :label="2">
|
||||
<view class="flex-col-center" @tap="goCart">
|
||||
<image class="w-60rpx h-60rpx" src="/static/icon/cart.png" />
|
||||
<view class="c-#0094ff text-20rpx">购物车</view>
|
||||
</view>
|
||||
</tm-badge>
|
||||
<view class="flex-1 ml-8 rounded-3 text-center bg-#0094ff py-2 c-white" @tap="state.showSkuDialog = true">加入购物车</view>
|
||||
</view>
|
||||
</template>
|
||||
</crud-layout>
|
||||
<product-sku v-model="state.showSkuDialog" :goodsInfo="state.detail" @onSkuAddToCart="onSkuAddToCart" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -58,10 +71,13 @@ import { reactive } from "vue"
|
||||
import { prosperityShopApi } from "@/sheep/api"
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
import { displayPrice } from "@/sheep/utils/formatMoney"
|
||||
import ProductSku from "./components/product-sku.vue"
|
||||
import { hooks, router } from "@/sheep"
|
||||
|
||||
const state = reactive<any>({
|
||||
id: "",
|
||||
detail: {},
|
||||
showSkuDialog: false,
|
||||
})
|
||||
onLoad(async (option: any) => {
|
||||
if (!option.id) return uni.showToast({ title: "参数错误", icon: "error" })
|
||||
@@ -76,6 +92,20 @@ const getGoodsDetail = async (id: string) => {
|
||||
if (code != 0) return uni.showToast({ title: msg || "商品详情获取失败", icon: "none" })
|
||||
state.detail = data
|
||||
}
|
||||
|
||||
// 选择sku确认加入到购物车
|
||||
const onSkuAddToCart = (sku: any) => {
|
||||
console.log(sku)
|
||||
|
||||
// cartStore.addGoodsItemToCart({ ...state.detail, ...sku, productId: sku.skuId })
|
||||
// cartStore.updateShopCart()
|
||||
state.showSkuDialog = false
|
||||
}
|
||||
|
||||
const goCart = async () => {
|
||||
const isLogin = await hooks.useCheckLogin()
|
||||
if (isLogin) router.jump("/pages/prosperity-shop/goods-cart")
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -14,14 +14,8 @@
|
||||
</view>
|
||||
<view v-if="state.detail.id" class="card p-20rpx mt-10rpx mx-20rpx">
|
||||
<view class="w-full sub-text-32 truncate">{{ state.detail.name }}</view>
|
||||
<view class="sub-text-24 mt-1">
|
||||
<text class="c-#0094ff! mr-20rpx px-2 bg-#0094ff22 rounded-2">{{ state.detail.status == "0" ? "开业中" : "未开业" }}</text>
|
||||
<text class="rounded-2 c-#0094ff px-2 bg-#0094ff22 rounded-2">{{ state.detail.businessHours }}</text>
|
||||
</view>
|
||||
<view class="second-text-24 truncate mt-1">
|
||||
<text class="mr-20rpx">营业人 {{ state.detail.contactName }}·{{ state.detail.contactPhone }}</text>
|
||||
<text class="mr-20rpx">许可 {{ state.detail.licenseNo }}</text>
|
||||
</view>
|
||||
<text class="sub-text-24 c-#0094ff! px-2 bg-#0094ff22 rounded-2 mr-4">营业</text>
|
||||
<text class="second-text-24 truncate mt-1">营业人 {{ state.detail.contactName }}·{{ state.detail.contactPhone }}</text>
|
||||
<view class="second-text-26 mt-1">
|
||||
<image class="w-24rpx h-24rpx mr-1" src="@/static/page/address.svg" />
|
||||
<text>{{ state.detail.address }}</text>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
<view class="second-text-26 text-center mb-2 mt-10">
|
||||
<text>联系热线:</text>
|
||||
<text @click="doPhone('18837698126')">18837698126</text>
|
||||
<text @click="doPhone('18367908152')">18367908152</text>
|
||||
|
||||
<text @click="doPhone('15657370065')">15657370065</text>
|
||||
</view>
|
||||
|
||||
@@ -143,10 +143,10 @@ 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 { useOnlineCartStore } from "@/sheep/stores/online-cart"
|
||||
import treeToList from "@/sheep/utils/tree-to-list"
|
||||
|
||||
const cartStore = useCartStore()
|
||||
const cartStore = useOnlineCartStore()
|
||||
|
||||
const state = reactive<any>({
|
||||
params: {
|
||||
|
||||
@@ -57,20 +57,15 @@
|
||||
|
||||
<view class="card p-20rpx mb-20rpx" v-for="(v, i) in pageHook.list" :key="i" @tap="toDetail(v)">
|
||||
<view class="flex">
|
||||
<image class="w-150rpx h-150rpx bg-#eeeeee rounded-12rpx" :src="filePath(v.images)" mode="aspectFill" />
|
||||
<image class="w-160rpx h-160rpx bg-#eeeeee rounded-12rpx" :src="filePath(v.images)" mode="aspectFill" />
|
||||
<view class="ml-20rpx flex-1 overflow-hidden">
|
||||
<view class="sub-text-30 truncate">{{ v.name }}</view>
|
||||
<view class="second-text-26 truncate">
|
||||
<text class="mr-20rpx">{{ v.contactName }}</text>
|
||||
<text class="mr-20rpx">
|
||||
<view class="sub-text-32 truncate">{{ v.name }}222222222222222222222222 </view>
|
||||
<view class="second-text-26 flex justify-between my-6rpx">
|
||||
<view>
|
||||
<image class="w-24rpx h-24rpx mr-1" src="@/static/page/phone.svg" />
|
||||
<text @tap.stop="doPhone(v.contactPhone)">{{ v.contactPhone }}</text>
|
||||
</text>
|
||||
<text>{{ v.email }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text class="c-#0094ff! sub-text-26 px-2 bg-#0094ff22 rounded-2 mr-2">营业</text>
|
||||
<text class="c-#0094ff! sub-text-26 px-2 bg-#0094ff22 rounded-2">{{ v.businessHours }}</text>
|
||||
</view>
|
||||
<text class="c-#0094ff! sub-text-26 px-2 bg-#0094ff22 rounded-2">营业</text>
|
||||
</view>
|
||||
<view class="second-text-26">
|
||||
<image class="w-24rpx h-24rpx mr-1" src="@/static/page/address.svg" />
|
||||
@@ -83,21 +78,21 @@
|
||||
<view class="w-160rpx flex-col items-center mr-20rpx" v-for="(pV, pI) in v.featuredProducts" :key="pI">
|
||||
<image class="w-160rpx h-160rpx rounded-12rpx bg-#eeeeee" :src="filePath(pV.coverImage)" mode="aspectFill" />
|
||||
<view class="w-full mt-4rpx sub-text-24 truncate">{{ pV.title }}</view>
|
||||
<view class="w-full flex justify-between pr-1">
|
||||
<view class="w-full flex justify-between">
|
||||
<text class="main-text-26 color-red!">
|
||||
<text class="text-22rpx">¥</text>
|
||||
<text>{{ pV.priceType == "1" ? displayPrice(pV.minPrice, "") : displayPrice(pV.spuPrice, "") }}</text>
|
||||
</text>
|
||||
<text class="sub-text-24">{{ pV.unit || "" }}</text>
|
||||
</view>
|
||||
<view class="w-full flex justify-between pr-1">
|
||||
<text class="second-text-24 line-through">
|
||||
<template v-if="pV.priceType == '2'">
|
||||
<text class="text-22rpx">¥</text>
|
||||
<text>{{ displayPrice(pV.originalPrice, "") }}</text>
|
||||
</template>
|
||||
</text>
|
||||
<text class="second-text-24">库存{{ pV.totalStock }}</text>
|
||||
</view>
|
||||
<view class="w-full flex justify-between second-text-24">
|
||||
<text>{{ pV.unit || "" }}</text>
|
||||
<text>库存{{ pV.totalStock }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -23,18 +23,6 @@ export default {
|
||||
method: "GET",
|
||||
params,
|
||||
}),
|
||||
getShopCar: (params: any) =>
|
||||
request({
|
||||
url: `/hard/hard-car/app/mch-detail`,
|
||||
method: "GET",
|
||||
params,
|
||||
}),
|
||||
updateShopCar: (data: any) =>
|
||||
request({
|
||||
url: `/hard/hard-car/app/save-or-upload`,
|
||||
method: "POST",
|
||||
data,
|
||||
}),
|
||||
checkSpuStock: (params) => {
|
||||
return request({
|
||||
url: "/canteen/canteenOnlineSpu/app/checkSpuStock",
|
||||
|
||||
@@ -25,6 +25,18 @@ export default {
|
||||
method: "GET",
|
||||
params,
|
||||
}),
|
||||
getShopCar: (params: any) =>
|
||||
request({
|
||||
url: `/hard/hard-car/app/mch-detail`,
|
||||
method: "GET",
|
||||
params,
|
||||
}),
|
||||
updateShopCar: (data: any) =>
|
||||
request({
|
||||
url: `/hard/hard-car/app/save-or-upload`,
|
||||
method: "POST",
|
||||
data,
|
||||
}),
|
||||
/**
|
||||
* 预约时间列表
|
||||
*/
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { defineStore } from "pinia"
|
||||
import { foodApi } from "../api"
|
||||
import { orderApi } from "../api"
|
||||
|
||||
export const useCartStore = defineStore("cartStore", {
|
||||
export const useOnlineCartStore = defineStore("onlineCartStore", {
|
||||
state: () => ({
|
||||
cart: JSON.parse(uni.getStorageSync("onlineShopCart") || "[]"),
|
||||
shopMerchantId: uni.getStorageSync("onlineShopMerchantId") || "",
|
||||
}),
|
||||
getters: {
|
||||
totalCount(state) {
|
||||
return state.cart.reduce((prev: string, cur: any) => {
|
||||
return state.cart.reduce((prev: number, cur: { productCount: number }) => {
|
||||
return prev + cur.productCount
|
||||
}, 0)
|
||||
},
|
||||
@@ -58,7 +58,7 @@ export const useCartStore = defineStore("cartStore", {
|
||||
await this.getShopCart()
|
||||
},
|
||||
async getShopCart() {
|
||||
const { data } = await foodApi.getShopCar({ merchantId: this.shopMerchantId, hardType: "SUPERMARKET" })
|
||||
const { data } = await orderApi.getShopCar({ merchantId: this.shopMerchantId, hardType: "SUPERMARKET" })
|
||||
this.saveShopCart(data ?? [])
|
||||
},
|
||||
async updateShopCart() {
|
||||
@@ -70,7 +70,7 @@ export const useCartStore = defineStore("cartStore", {
|
||||
productId: v.productId,
|
||||
}
|
||||
})
|
||||
const { code }: any = await foodApi.updateShopCar({ merchantId: this.shopMerchantId, list, hardType: "SUPERMARKET" })
|
||||
const { code }: any = await orderApi.updateShopCar({ merchantId: this.shopMerchantId, list, hardType: "SUPERMARKET" })
|
||||
if (code == 0) return await this.getShopCart()
|
||||
uni.showToast({ title: "更新购物车失败", icon: "none" })
|
||||
},
|
||||
@@ -0,0 +1,69 @@
|
||||
import { defineStore } from "pinia"
|
||||
import { orderApi } from "../api"
|
||||
|
||||
export const useProsperityCartStore = defineStore("prosperityCartStore", {
|
||||
state: () => ({
|
||||
cartList: [],
|
||||
}),
|
||||
getters: {
|
||||
totalCount(state) {
|
||||
return state.cartList.reduce((prev: number, cur: { productCount: number }) => {
|
||||
return prev + cur.productCount
|
||||
}, 0)
|
||||
},
|
||||
totPrice(state) {
|
||||
return state.cartList
|
||||
.map((item: any) => Number(item.totalPrice))
|
||||
.reduce((prev: number, cur: number) => prev + cur, 0)
|
||||
.toFixed(2)
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
addGoodsItemToCart(goodsItem: any) {
|
||||
const findResult = this.cartList.find((item: any) => {
|
||||
return item.productId === goodsItem.productId
|
||||
})
|
||||
if (!findResult) {
|
||||
this.cartList.unshift(goodsItem)
|
||||
} else {
|
||||
findResult.productCount++
|
||||
}
|
||||
uni.setStorageSync("onlineShopCart", JSON.stringify(this.cartList))
|
||||
},
|
||||
async addProductCount(productId: string) {
|
||||
this.cartList.forEach((item: any) => {
|
||||
if (item.productId === productId) {
|
||||
item.productCount++
|
||||
}
|
||||
})
|
||||
await this.updateShopCart()
|
||||
await this.getShopCart()
|
||||
},
|
||||
async removeProductCount(productId: string) {
|
||||
this.cartList.forEach((item: any) => {
|
||||
if (item.productId === productId) {
|
||||
item.productCount--
|
||||
}
|
||||
})
|
||||
await this.updateShopCart()
|
||||
await this.getShopCart()
|
||||
},
|
||||
async getShopCart(merchantId: string) {
|
||||
const { data } = await orderApi.getShopCar({ merchantId, hardType: "SUPERMARKET" })
|
||||
this.cartList = data
|
||||
},
|
||||
async updateShopCart() {
|
||||
const list = this.cartList
|
||||
.filter((v) => v.productCount && v.productCount > 0)
|
||||
.map((v) => {
|
||||
return {
|
||||
productCount: v.productCount,
|
||||
productId: v.productId,
|
||||
}
|
||||
})
|
||||
const { code }: any = await orderApi.updateShopCar({ merchantId: this.shopMerchantId, list, hardType: "SUPERMARKET" })
|
||||
if (code == 0) return await this.getShopCart()
|
||||
uni.showToast({ title: "更新购物车失败", icon: "none" })
|
||||
},
|
||||
},
|
||||
})
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
Reference in new issue
Block a user