购物车规格回显;修改超市详情轮播图

This commit is contained in:
ctw committed 2025-01-12 22:19:30 +08:00
1 parent d5a8a848be
commit b06b6a0974
6 files changed
+300 -307

No files matched your search

+74 -82
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref, reactive, withDefaults, defineProps, defineEmits } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import { ref, reactive, withDefaults, defineProps, defineEmits } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { hooks, router } from "@@/index"
import { merchantApi } from "@@/api"
@@ -8,101 +8,93 @@ import { merchantApi } from "@@/api"
const emit = defineEmits(["update:modelValue", "add", "remove"])
export type Props = {
mode: "default" | "car",
productId: number | null,
modelValue: number,
pic: string,
name: string,
price: any,
marketPrice: number,
salesCount: number,
stock: number,
count: number,
mode: "default" | "car"
productId: number | null
modelValue: number
pic: string
name: string
price: any
marketPrice: number
salesCount: number
stock: number
count: number
}
const props = withDefaults(defineProps<Props>(), {
mode: "default",
productId: null,
modelValue: 0,
pic: '',
name: '',
price: 0,
marketPrice: 0,
salesCount: 0,
stock: 0,
count: 0,
});
const state = reactive<any>({
mode: "default",
productId: null,
modelValue: 0,
pic: "",
name: "",
price: 0,
marketPrice: 0,
salesCount: 0,
stock: 0,
count: 0,
})
const state = reactive<any>({})
onLoad(() => {
});
onShow(() => {
})
onLoad(() => {})
onShow(() => {})
const add = () => {
if (props.modelValue >= 99) {
emit('update:modelValue', 99);
return
}
emit('update:modelValue', props.modelValue + 1)
emit('add')
if (props.modelValue >= 99) {
emit("update:modelValue", 99)
return
}
emit("update:modelValue", props.modelValue + 1)
emit("add")
}
const remove = () => {
if (props.modelValue < 0) {
emit('update:modelValue', 0);
return
}
emit('update:modelValue', props.modelValue - 1)
emit('remove')
if (props.modelValue < 0) {
emit("update:modelValue", 0)
return
}
emit("update:modelValue", props.modelValue - 1)
emit("remove")
}
</script>
<template>
<view :class="[props.mode == 'car' ? 'car_border' : '']"
class="flex-row items-start card p-x-15rpx p-y-25rpx m-b-20rpx"
@tap="props.productId && router.jump('/pages/merchant/product-detail', { id: props.productId })">
<image v-if="props.mode == 'default'" class=" size-180rpx rounded-12rpx" :src="props.pic" mode="aspectFill" />
<image v-if="props.mode == 'car'" class=" size-120rpx rounded-12rpx" :src="props.pic" mode="aspectFill" />
<view class="flex-1 m-l-20rpx">
<view class="sub-text-28 show-line">{{ props.name }}</view>
<view class="m-t-10rpx flex-row items-center">
<view class="second-text-32 color-red!">
¥{{ hooks.useMoney(props.price) }}
</view>
<view v-if="props.mode == 'default'" class="m-l-20rpx second-text-24 line-through">
¥{{ hooks.useMoney(props.marketPrice) }}
</view>
</view>
<view v-if="props.mode == 'car'" class="m-t-10rpx second-text-28">
x{{ props.count }}
</view>
<view v-if="props.mode == 'default'" class="flex-row items-center MT 10rpx">
<view class="second-text-24">{{ hooks.useFormatNum("库存", "", props.stock) }}</view>
<view class="w-1px h-20rpx m-x-5rpx bg-#999" />
<view class="second-text-24">{{ hooks.useFormatNum("销量", "", props.salesCount) }}</view>
</view>
<view class="flex-row items-center justify-end m-t-20rpx">
<view class="flex-row-center size-40rpx rounded-full border-1px border-solid border-color-#0094ff"
@tap.stop="remove">
<view class="iconfont icon-a--" />
</view>
<view class="sub-text-28 m-x-20rpx">{{ props.modelValue }}</view>
<view class="flex-row-center size-40rpx rounded-full bg-#0094ff" @tap.stop="add">
<view class="font-size-40rpx color-white iconfont icon-a-" />
</view>
</view>
</view>
</view>
<view
:class="[props.mode == 'car' ? 'car_border' : '']"
class="flex-row items-start card p-x-15rpx p-y-25rpx m-b-20rpx"
@tap="props.productId && router.jump('/pages/merchant/product-detail', { id: props.productId })"
>
<image v-if="props.mode == 'default'" class="size-180rpx rounded-12rpx" :src="props.pic" mode="aspectFill" />
<image v-if="props.mode == 'car'" class="size-120rpx rounded-12rpx" :src="props.pic" mode="aspectFill" />
<view class="flex-1 m-l-20rpx">
<view class="sub-text-28 show-line">{{ props.name }}</view>
<view class="m-t-10rpx flex-row items-center">
<view class="second-text-32 color-red!"> ¥{{ hooks.useMoney(props.price) }} </view>
<view v-if="props.mode == 'default'" class="m-l-20rpx second-text-24 line-through">
¥{{ hooks.useMoney(props.marketPrice) }}
</view>
</view>
<view v-if="props.mode == 'car'" class="m-t-10rpx second-text-28"> x{{ props.count }} </view>
<view v-if="props.mode == 'default'" class="flex-row items-center MT 10rpx">
<view class="second-text-24">{{ hooks.useFormatNum("库存", "", props.stock) }}</view>
<view class="w-1px h-20rpx m-x-5rpx bg-#999" />
<view class="second-text-24">{{ hooks.useFormatNum("销量", "", props.salesCount) }}</view>
</view>
<view class="flex-row items-center justify-end m-t-20rpx">
<view
class="flex-row-center size-40rpx rounded-full border-1px border-solid border-color-#0094ff"
@tap.stop="remove"
>
<view class="iconfont icon-a--" />
</view>
<view class="sub-text-28 m-x-20rpx">{{ props.modelValue }}</view>
<view class="flex-row-center size-40rpx rounded-full bg-#0094ff" @tap.stop="add">
<view class="font-size-40rpx color-white iconfont icon-a-" />
</view>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.car_border {
border: 1px solid #f2f2f2;
border: 1px solid #f2f2f2;
}
</style>
</style>
+4 -1
View File
@@ -14,10 +14,12 @@
:key="v.id"
:productId="v.productId"
:merchantId="v.merchantId"
:picUrl="v.productPic"
:picUrl="filePath(v.productPic)"
:productName="v.productName"
:productCount="v.productCount"
:productPrice="v.productPrice"
:spec="v.spec"
:unit="v.unit"
@add="(v) => emit('add', v)"
@remove="(v) => emit('remove', v)"
/>
@@ -31,6 +33,7 @@
</template>
<script setup lang="ts">
import { filePath } from "@/sheep/utils/file"
import ProductRow from "./product-row.vue"
import ProductTotal from "./product-total.vue"
@@ -9,6 +9,7 @@
<image class="size-140rpx rounded-12rpx" :src="props.picUrl" mode="aspectFill" />
<view class="flex-1 m-l-20rpx">
<view class="sub-text-28 show-line">{{ props.productName }}</view>
<view class="sub-text-24 show-line">规格:{{ "" + props.spec + props.unit }}</view>
<view class="m-t-10rpx flex-row items-center">
<!-- <view class="second-text-32 color-red!"> ¥{{ hooks.useMoney(props.price) }} </view> -->
<!-- <view class="m-l-20rpx second-text-24 line-through"> ¥{{ hooks.useMoney(props.marketPrice) }} </view> -->
@@ -61,6 +62,8 @@ export type Props = {
productPrice?: number
salesCount?: number
stock?: number
spec?: string
unit?: string
onClickAddToCar?: () => void
}
const props = withDefaults(defineProps<Props>(), {
@@ -73,6 +76,8 @@ const props = withDefaults(defineProps<Props>(), {
productPrice: 0,
salesCount: 0,
stock: 0,
spec: "",
unit: "",
})
const handleClickAddToCar = () => {
+4 -2
View File
@@ -3,8 +3,8 @@
<tm-sticky>
<!-- start 轮播 start -->
<z-swiper>
<z-swiper-item v-for="(v, i) in state.detail.picUrl?.split(',')" :key="i">
<image class="w-100vw h-400rpx" :src="filePath(state.detail?.swiperPic)" mode="aspectFill" />
<z-swiper-item v-for="(v, i) in state.detail.swiperPic?.split(',')" :key="i">
<image class="w-100vw h-400rpx" :src="filePath(v)" mode="aspectFill" />
</z-swiper-item>
</z-swiper>
<!-- end 轮播 end -->
@@ -185,6 +185,8 @@ const getPorduct = async () => {
// productName: target.name,
merchantId: state.merchantId,
categoryId: target.id,
current: 1,
size: 9999,
})
state.goodsList = data.records
// state.goodsList.forEach((i) => {
+65 -65
View File
@@ -1,68 +1,68 @@
import request from "@/sheep/utils/request";
import request from "@/sheep/utils/request"
export default {
getSupermarketSpuCategory: (params: any) =>
request({
url: `/supermarket/supermarketCategory/app/simpleAll`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
getSupermarketSpuList: (data: any) =>
request({
url: `/supermarket/supermarketSpu/app/selectListAll`,
method: "POST",
data,
custom: {
showLoading: false,
},
}),
getSupermarketSpuDetail: (params: any) =>
request({
url: `/supermarket/supermarketSpu/app/SpuDetails`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
getSupermarketSpuCategory: (params: any) =>
request({
url: `/supermarket/supermarketCategory/app/simpleAll`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
getSupermarketSpuList: (data: any) =>
request({
url: `/supermarket/supermarketSpu/app/selectListAll`,
method: "POST",
data,
custom: {
showLoading: false,
},
}),
getSupermarketSpuDetail: (params: any) =>
request({
url: `/supermarket/supermarketSpu/app/SpuDetails`,
method: "GET",
params,
custom: {
showLoading: false,
},
}),
// del: (params: any) =>
// request({
// url: `/sys/user/face-delete`,
// method: "DELETE",
// params,
// custom: {
// showLoading: false,
// },
// }),
// create: (data: any) =>
// request({
// url: `/sys/user/face-create`,
// method: "POST",
// data,
// custom: {
// showLoading: false,
// },
// }),
// get: (params: any) =>
// request({
// url: `/sys/user/face-get`,
// method: "GET",
// params,
// custom: {
// showLoading: false,
// },
// }),
// put: (data: any) =>
// request({
// url: `/sys/user/face-update`,
// method: "PUT",
// data,
// custom: {
// showLoading: false,
// },
// }),
};
// del: (params: any) =>
// request({
// url: `/sys/user/face-delete`,
// method: "DELETE",
// params,
// custom: {
// showLoading: false,
// },
// }),
// create: (data: any) =>
// request({
// url: `/sys/user/face-create`,
// method: "POST",
// data,
// custom: {
// showLoading: false,
// },
// }),
// get: (params: any) =>
// request({
// url: `/sys/user/face-get`,
// method: "GET",
// params,
// custom: {
// showLoading: false,
// },
// }),
// put: (data: any) =>
// request({
// url: `/sys/user/face-update`,
// method: "PUT",
// data,
// custom: {
// showLoading: false,
// },
// }),
}
+148 -157
View File
@@ -1,175 +1,166 @@
import Request from "luch-request";
import { isEmpty } from "radash";
import Request from "luch-request"
import { isEmpty } from "radash"
import { userApi } from "@@/api";
import { router, constant } from "@@/index";
import { userApi } from "@@/api"
import { router, constant } from "@@/index"
const options = {
// 显示操作成功消息 默认不显示
showSuccess: false,
// 成功提醒 默认使用后端返回值
successMsg: "",
// 显示失败消息 默认显示
showError: true,
// 失败提醒 默认使用后端返回信息
errorMsg: "",
// 显示请求时loading模态框 默认显示
showLoading: true,
// loading提醒文字
loadingMsg: "加载中",
// 需要授权才能请求 默认放开
auth: false,
};
// 显示操作成功消息 默认不显示
showSuccess: false,
// 成功提醒 默认使用后端返回值
successMsg: "",
// 显示失败消息 默认显示
showError: true,
// 失败提醒 默认使用后端返回信息
errorMsg: "",
// 显示请求时loading模态框 默认显示
showLoading: true,
// loading提醒文字
loadingMsg: "加载中",
// 需要授权才能请求 默认放开
auth: false,
}
let LoadingInstance = {
target: null,
count: 0,
};
target: null,
count: 0,
}
function closeLoading() {
if (LoadingInstance.count > 0) LoadingInstance.count--;
if (LoadingInstance.count === 0) uni.hideLoading();
if (LoadingInstance.count > 0) LoadingInstance.count--
if (LoadingInstance.count === 0) uni.hideLoading()
}
const http = new Request({
baseURL: import.meta.env.VITE_API_URL,
timeout: 8000,
method: "GET",
header: {
Accept: "*/*",
"Content-Type": "application/json;charset=UTF-8",
},
withCredentials: true,
custom: options,
});
baseURL: import.meta.env.VITE_API_URL,
timeout: 8000,
method: "GET",
header: {
Accept: "*/*",
"Content-Type": "application/json;charset=UTF-8",
},
withCredentials: true,
custom: options,
})
http.interceptors.request.use(
(config) => {
const tokenKey = constant.storageConstant.TOKEN;
const tokenStorage = uni.getStorageSync(tokenKey);
const config_header: any = config?.header;
// 添加终端类型
const isToc = import.meta.env.VITE_IS_TOC;
if (isToc === "true") {
config_header["CLIENT-TOC"] = "Y";
}
config_header["TENANT-ID"] = "1";
if (
config.url != "/sys/auth/refresh-token" &&
tokenStorage &&
tokenStorage.access_token &&
config_header
) {
config_header.Authorization = `Bearer ${tokenStorage.access_token}`;
}
if (config.custom && config.custom.showLoading) {
LoadingInstance.count++;
LoadingInstance.count === 1 &&
uni.showLoading({
title: config.custom.loadingMsg,
mask: true,
fail: () => {
uni.hideLoading();
},
});
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
(config) => {
const tokenKey = constant.storageConstant.TOKEN
const tokenStorage = uni.getStorageSync(tokenKey)
const config_header: any = config?.header
// 添加终端类型
const isToc = import.meta.env.VITE_IS_TOC
if (isToc === "true") {
config_header["CLIENT-TOC"] = "Y"
}
config_header["TENANT-ID"] = "1"
if (config.url != "/sys/auth/refresh-token" && tokenStorage && tokenStorage.access_token && config_header) {
config_header.Authorization = `Bearer ${tokenStorage.access_token}`
}
if (config.custom && config.custom.showLoading) {
LoadingInstance.count++
LoadingInstance.count === 1 &&
uni.showLoading({
title: config.custom.loadingMsg,
mask: true,
fail: () => {
uni.hideLoading()
},
})
}
return config
},
(error) => {
return Promise.reject(error)
},
)
http.interceptors.response.use(
async (response) => {
response.config &&
response.config.custom &&
response.config.custom.showLoading &&
closeLoading();
if (response.config.url === "/auth/oauth2/token") {
return Promise.resolve({
code: 0,
data: response.data,
msg: null,
});
}
if (response.data.code !== 0) {
if (
response.config &&
response.config.custom &&
response.config.custom.showError
) {
switch (response.data.code) {
case 401:
setTimeout(() => {
const tokenKey = constant.storageConstant.TOKEN;
const userInfoKey = constant.storageConstant.USERINFO;
uni.removeStorageSync(tokenKey);
uni.removeStorageSync(userInfoKey);
router.jump("/pages/tabbar/my", {}, 2);
}, 500);
break;
default:
uni.showToast({
title: response.data.msg || "服务器开小差啦,请稍后再试~",
icon: "none",
mask: true,
});
break;
}
return Promise.resolve(response.data);
}
}
if (
response.data.code === 200 &&
response.data.message !== "" &&
response.config &&
response.config.custom &&
response.config.custom.showSuccess
) {
uni.showToast({
title: response.config.custom.successMsg || response.data.message,
icon: "none",
});
}
const tokenKey = constant.storageConstant.TOKEN;
const tokenStorage = uni.getStorageSync(tokenKey);
if (
!isEmpty(tokenStorage) &&
response.config.url != "/sys/auth/refresh-token"
) {
const { refresh_token, expiresTime } = tokenStorage;
if (!isEmpty(refresh_token) && !isEmpty(expiresTime)) {
const now = new Date().getTime();
const remain = expiresTime - now;
if (remain <= 1000 * 60 * 20) {
const _pa = { refreshToken: refresh_token };
const refreshData = await userApi.refreshToken(_pa);
if (!isEmpty(refreshData.data)) {
uni.setStorageSync(tokenKey, refreshData.data);
}
}
}
}
return Promise.resolve(response.data);
},
(error) => {
console.log(error);
async (response) => {
response.config && response.config.custom && response.config.custom.showLoading && closeLoading()
if (response.config.url === "/auth/oauth2/token") {
return Promise.resolve({
code: 0,
data: response.data,
msg: null,
})
}
if (response.data.code !== 0) {
if (response.config && response.config.custom && response.config.custom.showError) {
switch (response.data.code) {
case 401:
setTimeout(() => {
const tokenKey = constant.storageConstant.TOKEN
const userInfoKey = constant.storageConstant.USERINFO
uni.removeStorageSync(tokenKey)
uni.removeStorageSync(userInfoKey)
router.jump("/pages/tabbar/my", {}, 2)
}, 500)
break
default:
uni.showToast({
title: response.data.msg || "服务器开小差啦,请稍后再试~",
icon: "none",
mask: true,
})
break
}
return Promise.resolve(response.data)
}
}
if (
response.data.code === 200 &&
response.data.message !== "" &&
response.config &&
response.config.custom &&
response.config.custom.showSuccess
) {
uni.showToast({
title: response.config.custom.successMsg || response.data.message,
icon: "none",
})
}
if (response.data.code === 1) {
const tokenKey = constant.storageConstant.TOKEN
uni.removeStorageSync(tokenKey)
uni.showToast({ title: "登录已过期,请重新登录", icon: "none" })
router.jump("/pages/test/login")
}
const tokenKey = constant.storageConstant.TOKEN
const tokenStorage = uni.getStorageSync(tokenKey)
if (!isEmpty(tokenStorage) && response.config.url != "/sys/auth/refresh-token") {
const { refresh_token, expiresTime } = tokenStorage
if (!isEmpty(refresh_token) && !isEmpty(expiresTime)) {
const now = new Date().getTime()
const remain = expiresTime - now
if (remain <= 1000 * 60 * 20) {
const _pa = { refreshToken: refresh_token }
const refreshData = await userApi.refreshToken(_pa)
if (!isEmpty(refreshData.data)) {
uni.setStorageSync(tokenKey, refreshData.data)
}
}
}
}
return Promise.resolve(response.data)
},
(error) => {
console.log(error)
let errorMessage = error.data.msg;
if (error !== undefined) {
uni.showToast({
title: errorMessage || "",
icon: "none",
mask: true,
});
}
return false;
}
);
let errorMessage = error.data.msg
if (error !== undefined) {
uni.showToast({
title: errorMessage || "",
icon: "none",
mask: true,
})
}
return false
},
)
const request = (config: any) => {
return http.middleware(config);
};
return http.middleware(config)
}
export default request;
export default request