代码提交

This commit is contained in:
黄少君
2023-11-17 20:55:32 +08:00
parent 35b43ffd97
commit c3e62f8922
73 changed files with 1808 additions and 781 deletions

View File

@ -13,7 +13,7 @@ import Fly from 'flyio/dist/npm/wx'
// #endif
import { handleLoginFailure } from '@/utils'
import { VUE_APP_API_URL } from '@/config'
import { VUE_APP_API_URL, VUE_APP_UPLOAD_URL } from '@/config'
import cookie from '@/utils/cookie'
import { replace } from '@/utils/router'
@ -155,7 +155,7 @@ export const upload = (options)=>{
...options.headers,
Authorization: 'Bearer ' + token.accessToken,
},
url:options.url?`${VUE_APP_API_URL}${options.url}`:VUE_APP_API_URL+'/member/user/update-avatar',
url:options.url?`${VUE_APP_API_URL}${options.url}`:VUE_APP_UPLOAD_URL,
success:(res)=>resolve(res),
fail:(err)=>reject(err),
complete:()=>uni.hideLoading()

View File

@ -12,7 +12,7 @@ import { useRouter } from "@/hooks/useRouter";
import { createAnimation } from "@/utils/utils";
import { useScroll } from "@/hooks/useScroll";
const HEADER_HEIGHT = 40 // header高度
const HEADER_HEIGHT = 60 // header高度
const {goBack} = useRouter()
/**
@ -31,6 +31,10 @@ const {goBack} = useRouter()
*
*/
const props = defineProps({
scrollTop:{
type:Number,
default:()=>0
},
systemBarAreaBg: {
type: String,
default: () => '#FFFFFF00' // 透明 #FFFFFF00
@ -93,7 +97,8 @@ const {
bgChangeColor,
propUp,
showRight,
leftWidth
leftWidth,
scrollTop
} = toRefs(props)
const emits = defineEmits(['getSystemInfo', 'animation'])
@ -198,7 +203,8 @@ const scrollMaskStyle = computed(() => {
// 总高度
const containerHeight = computed(() => {
return (unref(heightInfo).statusBarHeight + HEADER_HEIGHT)
const marginTop = unref(menuInfo).height > 0 ? `${((HEADER_HEIGHT - unref(menuInfo).height))/2}` : 0
return (unref(heightInfo).statusBarHeight + HEADER_HEIGHT - marginTop)
})
let animation
@ -208,7 +214,6 @@ function doCreateAnimation() {
animation = createAnimation(0, scrollEnd, 0, 1)
}
const {scrollTop} = useScroll();
watch(scrollTop, () => {
if (!bgChangeByScroll.value) return
if (!animation) doCreateAnimation()

View File

@ -0,0 +1,89 @@
<!--
@name: LazyImage
@author: kahu4
@date: 2023-11-16 18:38
@description图片懒加载
@update: 2023-11-16 18:38
-->
<script setup>
import { getCurrentInstance, nextTick, onMounted, ref, toRefs } from "vue";
import { lazyLoading } from "@/utils/images";
/**
* @property {string|number} 图片的唯一标识 必填(要求和lazy-${id})
*/
const props = defineProps({
unique: {
type: [String, Number],
required: true
},
src: {
type: String,
required: true
},
mode: {
type: String
}
})
const {
unique,
src,
mode
} = toRefs(props)
const showTruePic = ref(false); // 是否展示真是地址
const _this = getCurrentInstance()
function observerImage() {
const intersectionObserver = uni.createIntersectionObserver(_this);
intersectionObserver.relativeToViewport()
intersectionObserver.observe(`.lazy-${ unique.value }`, (res) => {
if (res.intersectionRatio <= 0) return
showTruePic.value = true
})
}
onMounted(() => {
nextTick(observerImage);
})
</script>
<template>
<view :class="['lazy-image']">
<view :class="[`lazy-${unique}`,'lazy-image__inner']">
<image
v-if="showTruePic"
class="image-context"
:src="src"
:mode="mode"
/>
<image
class="image-context"
:src="lazyLoading"
v-else
/>
</view>
</view>
</template>
<style
scoped
lang="scss"
>
.lazy-image {
// 微信小程序不设置这个会炸裂
width: 100%;
height: 100%;
&__inner {
width: 100%;
height: 100%;
.image-context {
width: 100%;
height: 100%;
}
}
}
</style>

View File

@ -7,11 +7,14 @@
-->
<script setup>
import { toRefs } from "vue";
const props = defineProps({
text: {
type: String,
default: () => '加载中...'
},
showLine :{
type: Boolean,
default:true
}
})
const {text} = toRefs(props)
@ -19,7 +22,7 @@ const {text} = toRefs(props)
<template>
<view class="load-over flex flex-ai__center flex-jc__center">
<view class="line"></view>
<view class="line" v-if="showLine"></view>
<view class="text-box flex flex-ai__center flex-jc__center">
<view
:class="{text:true}"
@ -30,7 +33,7 @@ const {text} = toRefs(props)
{{ item }}
</view>
</view>
<view class="line"></view>
<view class="line" v-if="showLine"></view>
</view>
</template>
@ -39,7 +42,6 @@ const {text} = toRefs(props)
lang="scss"
>
.load-over {
font-size: 28rpx;
position: relative;
color: $tips-color;

View File

@ -5,9 +5,9 @@
* @descriptionindex.data
* @update: 2023-11-08 11:08
* */
import wechatIcon from "@/static/icon/pay/weixin.png";
import { wechatIcon } from "@/utils/images";
import { PayType } from "@/utils/paymentUtils";
import aliIcon from "@/static/icon/pay/zhifubao.png";
import { aliIcon } from "@/utils/images";
export const payRows = [
{

View File

@ -13,7 +13,7 @@ import Empty from "@/components/Empty/index.vue"
import ListLoadOver from "@/components/ListLoadOver/index.vue"
import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
import { useRouter } from "@/hooks/useRouter";
import emptyIcon from "@/static/icon/empty/收藏.png";
import {emptyCollectIcon} from "@/utils/images";
import Goods from "@/components/goodsComponents/Goods.vue";
import { computed, toRefs } from "vue";
@ -90,7 +90,7 @@ const colList = computed(() => [
</view>
<Empty
v-else
:iconSrc="emptyIcon"
:iconSrc="emptyCollectIcon"
>
暂时没有商品推荐哦~
</Empty>

View File

@ -0,0 +1,238 @@
<!--
@name: ReturnTop
@author: kahu
@date: 2023-11-16 14:05
@description返回顶部
@update: 2023-11-16 14:05
-->
<script setup>
import { useScroll } from "@/hooks/useScroll";
import { computed, onMounted, ref, toRefs, unref } from "vue";
import UvIcon from "@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue";
import { useScreen } from "@/hooks/useScreen";
import { useSystem } from "@/hooks/useSystem";
import { CacheKey } from "@/utils/config";
import { toTop } from "@/utils/images";
const {scrollTop, scrollToTop} = useScroll()
const {getSystemInfo} = useSystem();
/**
* @property {number} top 距离top多少显示
* @property {number[]} location 按钮位置(距离右下角)([x,y]
* @property {number} size 按钮大小
* @property {string} round 圆角大小
* @property {string} color 字体颜色
* @property {string} background 背景颜色
*/
const props = defineProps({
top: {
type: Number,
default:200
},
location: {
type: Array,
default: () => ([20, 200])
},
size: {
type: Number,
default: 80
},
round: {
type: String,
default: '50%'
},
background: {
type: String,
default: "#fff"
},
color: {
type: String,
default: "#333"
},
scrollTop:{
type:Number,
default:0
}
})
const {
top,
location,
size,
round,
background,
color
} = toRefs(props)
const computedStyle = computed(() => {
const width = `${ unref(size) }rpx`;
const height = `${ unref(size) }rpx`;
const scale = unref(scrollTop) >= unref(top) ? 1 : 0;
const y = unref(touchLocation)[1]>0?`${unref(touchLocation)[1]}px`:`calc(100vh - ${ unref(location)[1] || 200 }rpx - ${ unref(size) }rpx)`
const x = unref(touchLocation)[0]>0?`${unref(touchLocation)[0]}px`:`calc(100vw - ${ unref(location)[0] || 20 }rpx - ${ unref(size) }rpx)`
return {
width,
height,
scale,
top:y,
left:x,
background: unref(background),
color: unref(color),
borderRadius: unref(round),
}
})
const systemInfo = ref({
windowWidth:0,
windowHeight:0
}) // 系统信息
const touchLocation = ref([0, 0]) // 移动的位置 x y
let timeout // 浮动的时间
const isTouch = ref(false) // 是否正在浮动
function handleTouchstart(e) {
// 一秒以后设置正在浮动
timeout = setTimeout(()=>{
isTouch.value = true
},1000);
}
function handleTouchmove(e){
if(!unref(isTouch))return
if(e.changedTouches.length<1)return;
const {clientX,clientY} = e.changedTouches[0] // 手指的x y
let top = clientY - unref(size) / 2
let left = clientX - unref(size) / 2
// 判断边界
top<=0?top = 1:void 0
left<=0?left = 1:void 0
top>=(unref(systemInfo).safeArea.height || unref(systemInfo).windowHeight) - unref(size)/2?top=(unref(systemInfo).safeArea.height || unref(systemInfo).windowHeight)-unref(size)/2 :void 0
left>=unref(systemInfo).windowWidth?left=unref(systemInfo).windowWidth - unref(size) / 2:void 0
touchLocation.value = [left,top]
}
function handleTouchend(e){
timeout&&clearTimeout(timeout)
isTouch.value = false
// 判断是否移动数据
if(unref(touchLocation)[0]>0 || unref(touchLocation)[1]>0){
uni.setStorageSync(CacheKey.TOP_TOUCH_KEY,JSON.stringify(unref(touchLocation)))
}
}
const animation = ref(false)
function handleClick(){
if(unref(isTouch))return
animation.value = true
setTimeout(()=>{
scrollToTop()
},500)
setTimeout(()=>{
animation.value = false
},1200)
}
onMounted(async ()=>{
systemInfo.value = await getSystemInfo();
// 有默认touch设置默认touch
const touchStorageStr = uni.getStorageSync(CacheKey.TOP_TOUCH_KEY);
if(!!touchStorageStr){
touchLocation.value = JSON.parse(touchStorageStr)
}
})
</script>
<template>
<view
class="return-top"
:class="{touch:isTouch,click:animation}"
:style="computedStyle"
@touchstart="handleTouchstart"
@touchmove.stop="handleTouchmove"
@touchend="handleTouchend"
@click="handleClick"
>
<slot>
<image class="top-icon" :src="toTop" />
</slot>
</view>
</template>
<style
scoped
lang="scss"
>
.return-top {
position: fixed;
z-index: 9999;
background: #fff;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 10rpx #cccccc;
transition: scale .3s,box-shadow .3s;
//transform-origin: top right;
&:active {
}
.top-icon{
width: 60%;
height: 60%;
border-radius: 50%;
position: relative;
}
}
.touch{
animation: breathe 1s ease-in-out infinite alternate,bounce 700ms ease-in-out infinite alternate !important;
}
.click{
animation: bounce 400ms ease-in-out 1,track 800ms 400ms cubic-bezier(1,-0.1,.85,1.37) 1;
}
// 呼吸动画
@keyframes breathe {
from{
scale: .8!important;
box-shadow: 0 0 10rpx rgba(238, 109, 70, 0.8);
}
to{
scale: 1!important;
box-shadow: 0 0 50rpx 30px rgba(238, 109, 70, 0.3);
}
}
// 发射动画-抖动
@keyframes bounce {
0%,20%,40%,60%,80%,100%{
rotate: (-20deg);
}
5%,25%,45%,65%,85%{
rotate: (20deg);
}
}
// 发射动画-轨迹
@keyframes track {
from{
transform: translateY(0);
box-shadow: 0 100rpx 60rpx #ee6d46;
}
to{
transform: translateY(-1000px);
opacity: .2;
}
}
.shadow{
}
</style>

View File

@ -19,7 +19,7 @@
<view class="activity-header-more-info">{{ more }}</view>
<img
class="image"
src="@/static/images/next.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/next.png"
alt=""
>
</view>

View File

@ -44,12 +44,13 @@
>
<view
class="button"
:class="storeNum <= 1 && 'disabled'"
@click="handleCartNumberChange(curAttr,'minus')"
>
<uv-icon
name="minus"
color="#333"
size="12"
size="24rpx"
></uv-icon>
</view>
<view class="input">
@ -62,12 +63,13 @@
</view>
<view
class="button"
:class="storeNum >= curAttr.stock && 'disabled'"
@click="handleCartNumberChange(curAttr,'plus')"
>
<uv-icon
name="plus"
color="#333"
size="12"
size="24rpx"
></uv-icon>
</view>
</view>
@ -89,7 +91,7 @@
{{ item.attrName }}
</view>
<view class="goodAttrSelect-attr-content">
<space wrap="warp">
<space wrap="warp" gap>
<view
:class="{ attr: true, check: selectedAttr[index] === attr }"
v-for="(attr, attrIndex) in item.attrValueArr"
@ -102,6 +104,8 @@
</view>
<view class="goodAttrSelect-action">
<uv-button
v-if="curAttr"
:disabled="curAttr.stock===0 || storeNum===0"
round
block
type="primary"
@ -134,8 +138,13 @@ const productValue = ref(null)
const storeNum = ref(1)
const curAttr = ref(null)
const defaultSelectAttrStr = ref(undefined)
const selectAttrPanel = ref(false)
const customStyle = {
width: '40rpx',
height: '40rpx',
padding: '0px',
border: '1rpx solid #cccccc',
}
const handleGetDetail = async (id) => {
const detail = await getProductDetail(id)
@ -157,6 +166,9 @@ const handleGetDetail = async (id) => {
selectedAttr.value = unref(defaultSelectAttrStr).split(',')
curAttr.value = productValue.value[defaultSelectAttrStr.value]
}
if(storeNum.value>curAttr.value.stock){
storeNum.value = curAttr.value.stock
}
}
}
@ -164,6 +176,12 @@ const handleSelectAttr = (index, attr) => {
selectedAttr.value[index] = attr
let selectedAttrStr = selectedAttr.value.join(',')
curAttr.value = productValue.value[selectedAttrStr]
if(storeNum.value === 0 && curAttr.value.stock >0){
storeNum.value = 1
}
if(storeNum.value>curAttr.value.stock){
storeNum.value = curAttr.value.stock
}
}
const handleSubmit = () => {
@ -180,20 +198,21 @@ const handleSubmit = () => {
// })
// return
// }
let selectedAttrStr = selectedAttr.value.join(',')
emit('submit', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
emit('select', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
emit('onSelect', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
if(curAttr.value.stock!==0 && storeNum.value!==0){
let selectedAttrStr = selectedAttr.value.join(',')
emit('submit', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
emit('select', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
emit('onSelect', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
}
}
const {toast} = useInterface()
@ -208,13 +227,11 @@ function handleCartNumberInputChange(e, item) {
const value = Number(e.detail.value)
if (value <= 0) {
storeNum.value = 1
toast({title: '至少选一件哦~'})
}
if (value > item.stock) {
} else if (value > item.stock) {
storeNum.value = item.stock
toast({title: '超出库存啦~'})
} else {
storeNum.value = value
}
storeNum.value = value
}
/**
@ -225,13 +242,18 @@ function handleCartNumberInputChange(e, item) {
*/
function handleCartNumberChange(item, type = 'plus') {
if (type === 'plus') {
// +
if (storeNum.value + 1 > item.stock) return toast({title: '超出库存啦~'})
storeNum.value += 1
if (storeNum.value + 1 > item.stock){
storeNum.value =item.stock
} else{
storeNum.value += 1
}
} else {
// -
if (storeNum.value - 1 <= 0) return toast({title: '至少选一件哦~'})
storeNum.value -= 1
if (storeNum.value - 1 <= 0){
storeNum.value = 1
} else {
storeNum.value -= 1
}
}
}
@ -268,8 +290,9 @@ defineExpose({
}
.attr-info {
flex: 1;
max-width: calc(100% - 150rpx - 30rpx);
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
margin-left: 30rpx;
@ -277,6 +300,11 @@ defineExpose({
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
}
&-bottom {
@ -304,12 +332,13 @@ defineExpose({
}
&-attr {
padding: 40rpx 30rpx;
padding: 40rpx 30rpx 10rpx 0;
&.row {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 40rpx;
.goodAttrSelect-attr-title {
margin-bottom: 0;
@ -317,7 +346,7 @@ defineExpose({
}
&-title {
margin-bottom: 30rpx;
margin:0 0 30rpx 30rpx;
}
&-content {
@ -341,7 +370,7 @@ defineExpose({
display: flex;
justify-content: center;
align-items: center;
margin: 0 0 30rpx 30rpx;
&.check {
background: #333333;
color: #fff;
@ -363,20 +392,33 @@ defineExpose({
.button {
font-size: 32rpx;
width: 34rpx;
width: 40rpx;
aspect-ratio: 1/1;
border-radius: 5rpx;
border: 2rpx solid #cccccc;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
transition: all .3s;
border: 1px solid #999999;
&:active {
scale: 1.2;
}
&.disabled{
border-color: #dddddd;
:deep(.uv-icon__icon){
color: #dddddd !important;
}
&:active {
scale: 1;
}
}
}
}
.gap{
gap: 20rpx;
}
</style>

View File

@ -6,15 +6,15 @@
>
<view class="coupon-box">
<template v-if="!showEmpty">
<template v-for="item in couponList">
<view class="coupon-list" v-for="item in couponList">
<CouponItem
:coupons="item"
:type="'get'"
/>
</template>
</view>
</template>
<Empty
:iconSrc="emptyIcon"
:iconSrc="emptyCouponIcon"
v-else
>
暂时没有可领取的优惠券~
@ -31,7 +31,7 @@ import Empty from "@/components/Empty/index.vue"
import { getProductCoupon } from "@/api/coupon";
import CouponItem from "@/pages/discountCoupon/components/CouponItem.vue";
import Popup from '@/components/Popup/index.vue';
import emptyIcon from "@/static/icon/empty/优惠券.png";
import { emptyCouponIcon } from "@/utils/images";
const props = defineProps(["id"])
@ -91,6 +91,9 @@ defineExpose({
padding: 24rpx;
box-sizing: border-box;
width: 100%;
.coupon-list {
margin-bottom: 24rpx;
}
}
</style>

View File

@ -29,7 +29,7 @@
>
<view class="goods-list-model-label">{{ data.attrInfo.sku }}</view>
<view class="goods-list-model-action icon">
<image src="@/static/images/down.png" />
<image src="https://b2c-pro-static-dev.zkthink.com/static/images/down.png" />
</view>
</div>
</view>
@ -368,6 +368,9 @@ const handleSelectAttr = () => {
font-size: 24rpx;
color: #999999;
margin-right: 10rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&-value {
@ -375,6 +378,7 @@ const handleSelectAttr = () => {
font-size: 24rpx;
color: #333333;
margin-right: 10rpx;
display: -webkit-box;
}
&-action {

View File

@ -6,7 +6,8 @@
@update: 2023-11-02 18:30
-->
<script setup>
import { toRefs } from "vue";
import LazyImage from '@/components/LazyImage/index.vue'
import { computed, onBeforeUnmount, toRefs } from "vue";
import { GOODS_ITEM_TYPE } from "@/components/goodsComponents/utils/index.type";
import { useRouter } from "@/hooks/useRouter";
import { getRandom } from "@/utils/utils";
@ -61,6 +62,8 @@ const {
const {push} = useRouter()
const randomRatio = computed(()=>(`${1/getRandom(1,1.3)}`))
function toDetail() {
push({url: '/pages/goodsDetail/goodsDetail'}, {data: {id: goods.value.id}})
}
@ -77,14 +80,20 @@ function toDetail() {
class="goods-image"
:style="{
'width':imgWidth,
'aspect-ratio': ratio===true?`${1/getRandom(1,1.3)}`:ratio
'aspect-ratio': ratio===true?randomRatio:ratio
}"
>
<image
<LazyImage
:unique="goods.id"
:src="goods.image"
class="image"
:mode="ratio===true?'aspectFit':'aspectFill'"
/>
<!-- <image
:src="goods.image"
class="image"
:mode="ratio===true?'aspectFit':'aspectFill'"
/>-->
</view>
<!-- good info -->
<view
@ -156,7 +165,6 @@ function toDetail() {
justify-content: space-between;
.goods-image {
}
.goods-info {

View File

@ -130,7 +130,7 @@ const {row, showBtn, oldPrice, btnText} = toRefs(props)
flex-shrink: 0;
background: $primary-color;
color: $white-color;
font-size: 24rpx;
font-size: 18rpx;
}
.no-btn {

View File

@ -3,7 +3,6 @@
:class="['order']"
v-if="data"
>
<view
class="order-header"
@tap="toOrderInfo"
@ -61,7 +60,6 @@
<view class="total-price">¥{{ totalPrice }}</view>
</view>
</view>
<view v-if="data._status">
<view
class="order-actions"
@ -74,7 +72,7 @@
<view
v-if="data._status._type == 0"
class="order-actions-default"
@tap="handleCancel"
@tap="showModal(0)"
>
取消订单
</view>
@ -102,31 +100,34 @@
<view
v-if="data._status._type == 2"
class="order-actions-primary"
@tap="handleOrderTake"
@tap="showModal(2)"
>
确认收货
</view>
<view
v-if="['4'].includes(data._status._type)"
class="order-actions-default"
@tap="handleDelete"
@tap="showModal(1)"
>
删除订单
</view>
</view>
</view>
</view>
<Modal ref="modalRef" :content="modalTitle" @confirm="handleModalConfirm" />
</view>
</template>
<script setup>
import { ref } from 'vue';
import { computed, ref, unref } from 'vue';
import { orderCancel, orderDelete, orderTake } from '@/api/order'
import Modal from "@/components/Modal/index.vue"
import { useRouter } from "@/hooks/useRouter";
import { useInterface } from "@/hooks/useInterface";
const {push} = useRouter()
const {toast} = useInterface()
const emit = defineEmits(['refresh', 'pay'])
@ -143,28 +144,69 @@ const couponPrice = ref(props.data.couponPrice)
// 订单总价
const totalPrice = ref(props.data.totalPrice)
const handleCancel = async () => {
uni.showModal({
title: '提示',
content: '确认取消订单',
success: async (res) => {
if (res.confirm) {
await orderCancel({
id: data.value.orderId
})
data.value = null
uni.showToast({
title: '已取消',
duration: 2000
});
} else if (res.cancel) {
}
}
});
const modalRef = ref()
const modalType = ref(0) // 0取消订单 1删除订单 2确认收获
const modalTitle = computed(()=>{
const tipArr = ['确认取消订单吗?','确认删除订单吗?','确认要确认收货吗?']
return tipArr[modalType.value]
})
/**
* 弹窗确认
*/
function handleModalConfirm(){
const funcArr = [doCancelRequest,doDeleteRequest,doTakeRequest]
funcArr[modalType.value]()
}
/**
* 打开弹窗
* @param {number} type 0取消订单 1删除订单 2确认收获
*/
function showModal(type = 0){
modalType.value = type
unref(modalRef).show()
}
const toSelectRefundGood = () => {
/**
* 确认取消订单
* @returns {Promise<void>}
*/
async function doCancelRequest(){
await orderCancel({
id: data.value.orderId
})
emit('refresh')
toast({title: '已取消'});
}
/**
* 确认删除订单
* @returns {Promise<void>}
*/
async function doDeleteRequest(){
await orderDelete({
uni: data.value.orderId
})
emit('refresh')
toast({title: '删除成功'});
}
/**
* 确认收货
* @returns {Promise<void>}
*/
async function doTakeRequest(){
let option = {
uni: data.value.orderId,
}
await orderTake(option)
emit('refresh')
toast({title: '已收货'});
}
function toSelectRefundGood(){
push({url: '/pages/selectRefundGood/selectRefundGood'}, {
data: {
orderId: data.value.orderId,
@ -174,18 +216,12 @@ const toSelectRefundGood = () => {
})
}
const handlePay = () => {
function handlePay(){
emit('pay', data.value.orderId)
/* push({url: '/pages/selectPlay/selectPlay'}, {
data: {
key: data.value.unique,
orderId: data.value.orderId,
}
})*/
}
const toOrderInfo = () => {
function toOrderInfo() {
push({url: '/pages/orderInfo/orderInfo'}, {
data: {
key: data.value.unique,
@ -195,7 +231,7 @@ const toOrderInfo = () => {
}
const toEvaluate = (item) => {
function toEvaluate(item){
push({url: '/pages/evaluate/evaluate'}, {
data: {
unique: item.unique,
@ -205,52 +241,23 @@ const toEvaluate = (item) => {
}
const handleDelete = async () => {
uni.showModal({
title: '提示',
content: '确认取消订单',
success: async (res) => {
if (res.confirm) {
await orderDelete({
uni: data.value.orderId
})
data.value = null
uni.showToast({
title: '已删除',
duration: 2000
});
} else if (res.cancel) {
}
}
});
}
const handleOrderTake = async () => {
uni.showModal({
title: '提示',
content: '确认收货',
success: async (res) => {
if (res.confirm) {
let option = {
uni: data.value.orderId,
}
await orderTake(option)
emit('refresh')
uni.showToast({
title: '已收货',
duration: 2000
});
} else if (res.cancel) {
}
}
});
}
</script>
<style lang="scss">
<style lang="scss" scoped>
.order-header{
width: 100%;
box-sizing: border-box;
.order-logo,.order-status{
flex-shrink: 0;
}
.order-logo{
white-space: nowrap;
}
.order-status{
max-width: 80%;
text-align: right;
white-space: pre-wrap;
font-size: 22rpx;
}
}
</style>

View File

@ -42,7 +42,7 @@
:class="data.state === 3 && 'color-y'"
>{{ data.state === 3 ? '成功退款' : '待平台处理' }}
</text>
<text class="text">{{ data.state === 3 ? '成功' : '' }}退款¥{{data.refundAmount}}</text>
<text class="text">{{ data.state === 3 ? '成功' : '' }}退款¥{{data.refundAmount.toFixed(2)}}</text>
</view>
<view class="order-actions">
@ -52,14 +52,14 @@
<view class="order-actions-btns">
<view
class="order-actions-default"
@tap="handleDelete"
@tap="showModal(0)"
v-if="[3,4].includes(data.state)"
>
删除记录
</view>
<view
class="order-actions-default"
@tap="handleRevoke"
@tap="showModal(1)"
v-if="[0,1].includes(data.state)"
>
撤销申请
@ -88,17 +88,20 @@
</view>
</view>
<Modal ref="modalRef" :content="modalTitle" @confirm="confirmModal" />
</view>
</template>
<script setup>
import { ref } from 'vue';
import { computed, ref, unref } from 'vue';
import { afterSalesOrderDelete, afterSalesOrderRevoke } from '@/api/order'
import Modal from '@/components/Modal/index.vue'
import { useRouter } from "@/hooks/useRouter";
import { refundOrderStatus } from '@/config'
import { useInterface } from "@/hooks/useInterface";
const {push} = useRouter()
const {toast} = useInterface();
const emit = defineEmits(['refresh'])
@ -115,48 +118,54 @@ const couponPrice = ref(props.data.couponPrice)
// 订单总价
const totalPrice = ref(props.data.totalPrice)
// 删除记录
const handleDelete = async () => {
uni.showModal({
title: '提示',
content: '确认删除记录',
success: async (res) => {
if (res.confirm) {
await afterSalesOrderDelete({
id: data.value.id,
orderCode: data.value.orderCode
})
data.value = null
uni.showToast({
title: '已删除',
duration: 2000
});
} else if (res.cancel) {
}
}
});
const modalRef = ref()
const modalType = ref(0) // 0删除记录 1撤销申请
const modalTitle = computed(()=>{
const tipsArr = ['确认删除记录吗?','确认撤销申请吗?']
return tipsArr[modalType.value]
})
/**
* 打开弹窗
* @param {number} type 0删除记录 1撤销申请
*/
function showModal(type){
modalType.value = type
unref(modalRef).show()
}
// 撤销申请
const handleRevoke = async () => {
uni.showModal({
title: '提示',
content: '确认撤销申请吗',
success: async (res) => {
if (res.confirm) {
await afterSalesOrderRevoke({
id: data.value.id,
key: data.value.orderCode
})
data.value = null
uni.showToast({
title: '已撤销',
duration: 2000
});
} else if (res.cancel) {
}
}
});
/**
* 确认弹窗
*/
function confirmModal(){
const funcArr = [doDeleteRequest,doRevoke]
funcArr[modalType.value]()
}
/**
* 确认删除
* @returns {Promise<void>}
*/
async function doDeleteRequest(){
await afterSalesOrderDelete({
id: data.value.id,
orderCode: data.value.orderCode
})
data.value = null
toast({title: '已删除'});
}
/**
* 确认撤销
* @returns {Promise<void>}
*/
async function doRevoke(){
await afterSalesOrderRevoke({
id: data.value.id,
key: data.value.orderCode
})
data.value = null
toast({title: '已撤销'});
}
// 查看详情
@ -164,6 +173,7 @@ const toOrderInfo = () => {
push({url: '/pages/refundInfo/refundInfo'}, {
data: {
id: data.value.id,
orderId: data.value.orderId
}
})
}
@ -181,7 +191,6 @@ const toAddLogistics = () => {
// 再次申请
const toRefund = () => {
console.log(data.value)
push({url: '/pages/refund/refund'}, {
data: {
refundType: data.value.serviceType,

View File

@ -47,6 +47,10 @@ const handleClassObject = (props) => {
if (justify) {
className += ` yshop-space-justify-${ justify }`
}
if(props.gap){
className += ` gap`
}
classObject.value = className
}
@ -189,6 +193,10 @@ space {
&-border {
border-bottom: 1rpx solid #f9f9f9;
}
}
.gap{
gap:20rpx;
}
// #ifdef APP-PLUS

View File

@ -1,7 +1,6 @@
export const VUE_APP_API_URL = 'https://b2c-pro-api-dev.zkthink.com/app-api'
export const VUE_APP_RESOURCES_URL = 'https://h5.yixiang.co/static'
export const VUE_APP_UPLOAD_URL = VUE_APP_API_URL + '/infra/file/upload'
export const VUE_APP_STATIC_URL = "https://b2c-pro-static-dev.zkthink.com/" // 静态资源路径
const orderListStatus = {}
// -1:申请退款

View File

@ -16,8 +16,11 @@ export const useRouter = () => {
* 使用此方法的跳转获取参数必须使用本hooks的getParams方法获取路由参数
* 注意2.8.9+以后版本可以使用events参数传递一个方法对象和新打开的页面建立一个channel通讯getOpenerEventChannel获取到这个channel
* @docs: https://uniapp.dcloud.net.cn/api/router.html#navigateto
* @param options{any} 原始参数
* @param config{{type?:'navigateTo'|'redirectTo'|'reLaunch',data?:any,timeout?:number}}
* @param {object} options 原始参数
* @param {object} config 配置参数
* @param {'navigateTo'|'redirectTo'|'reLaunch'} config.type 跳转类型
* @param {object} config.data 跳转参数
* @param {number} config.timeout 延时时间
* type跳转类型默认navigateTo ; data跳转参数默认空对象 ; timeout跳转延时默认0
* @returns {Promise<boolean>}
*/
@ -86,8 +89,8 @@ export const useRouter = () => {
/**
* 返回
* @param options{any} 默认参数对象
* @param timeout{number} 延时跳转
* @param {object} options 默认参数对象
* @param {number} timeout 延时跳转
* @returns {Promise<unknown>}
*/
function goBack(options, timeout = 0) {
@ -121,8 +124,8 @@ export const useRouter = () => {
/**
* 获取跳转页参数解析对象
* @param options{any} onLoad函数的原始参数
* @returns {any}
* @param {object} options onLoad函数的原始参数
* @returns {object}
*/
function getParams(options) {
if (typeof options !== 'object') return {}
@ -135,7 +138,7 @@ export const useRouter = () => {
/**
* 预加载页面
* @param url
* @param {string} url 路径
* @returns {Promise<boolean>}
*/
function preLoad(url) {
@ -157,7 +160,12 @@ export const useRouter = () => {
/**
* 获取当前页面对象
* @returns {{prePage: ((Page.PageInstance<AnyObject, {}> & {})|null), currentPages: Array<Page.PageInstance<AnyObject, {}> & {}>, nowPage: ((Page.PageInstance<AnyObject, {}> & {})|null)}}
* @returns {
* {
* prePage: (Page.PageInstance<AnyObject, {}>|{}|null),
* currentPages: Array<Page.PageInstance<AnyObject, {}> & {}>,
* nowPage: (Page.PageInstance<AnyObject, {}>|{}|null)}
* }
*/
function getCurrentPage() {
const currentPages = getCurrentPages();
@ -190,7 +198,7 @@ export const useRouter = () => {
/**
* 校验URL
* @param options
* @param {object} options
*/
const checkUrl = (options) => {
if (!options.url) throw new Error('options 必须携带url参数')
@ -199,8 +207,8 @@ const checkUrl = (options) => {
/**
* 处理参数
* 如果有参数的情况使用encodeURIComponent + JSON.stringify格式化掉
* @param options
* @param data
* @param {object} options
* @param {object} data
*/
const processingParameter = (options, data) => {
if (Object.keys(data).length > 0) {

View File

@ -1,15 +1,27 @@
import { onPageScroll } from "@dcloudio/uni-app";
import { onLoad, onPageScroll } from "@dcloudio/uni-app";
import { onBeforeUnmount, ref } from "vue";
const scrollTop = ref(0)
export function useScroll(){
const scrollTop = ref(0)
onPageScroll((e)=>{
scrollTop.value = e.scrollTop
})
onBeforeUnmount(()=>{
scrollTop.value = 0
})
return {
scrollTop
function scrollToTop(){
uni.pageScrollTo({
scrollTop: 0,
duration: 500
})
}
return {
scrollTop,
scrollToTop
}
}

View File

@ -42,8 +42,8 @@ export function createApp() {
}
})
// #ifdef H5
// const vConsole = new VConsole()
// app.use(vConsole)
const vConsole = new VConsole()
app.use(vConsole)
// #endif
return {
app,

View File

@ -75,6 +75,13 @@
"enablePullDownRefresh": false
}
},
{
"path": "pages/shoppingCartJump/shoppingCart",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path": "pages/submitOrder/submitOrder",
"style": {
@ -268,7 +275,7 @@
},
"tabBar": {
"color": "#282828",
"selectedColor": "#eb3729",
"selectedColor": "#ee6d46",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"height": "50px",

View File

@ -171,7 +171,8 @@ const handleApplyForAfterSales = async () => {
push({url: '/pages/refundInfo/refundInfo'}, {
data: {
id: data.value.id,
}
},
type:"redirectTo"
})
}

View File

@ -1,7 +1,7 @@
<template>
<layout>
<Header>
<Header :scroll-top="scrollTop">
{{ title }}
</Header>
@ -12,7 +12,7 @@
v-for="(item, index) in main.address"
:key="index"
:options="options"
@click="handleAddressClick($event, item)"
@click="showModal( item)"
>
<view
:class="{ address: true, noBorder: index == 0 }"
@ -47,7 +47,7 @@
>
<image
class="image"
src="@/static/images/icon-edit.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/icon-edit.png"
alt=""
></image>
</view>
@ -57,7 +57,7 @@
</uv-swipe-action>
</template>
<Empty
:iconSrc="emptyIcon"
:iconSrc="emptyAddressIcon"
v-else
>
您还没有新增地址~
@ -75,6 +75,8 @@
</uv-button>
</view>
</view>
<ReturnTop :scroll-top="scrollTop" />
<Modal ref="modalRef" content="确认要删除地址吗?" @confirm="doDeleteRequest" />
</layout>
</template>
@ -84,12 +86,16 @@ import { ref, unref } from 'vue'
import { onLoad, onReachBottom } from '@dcloudio/uni-app'
import { useMainStore } from '@/store/store'
import Empty from '@/components/Empty/index.vue'
import emptyIcon from '@/static/icon/empty/地址.png'
import { emptyAddressIcon } from "@/utils/images";
import { getAddressDel, } from '@/api/address'
import { useRouter } from "@/hooks/useRouter";
import Header from "@/components/Header/index.vue"
import ReturnTop from "@/components/ReturnTop/index.vue";
import { useScroll } from "@/hooks/useScroll";
import Modal from "@/components/Modal/index.vue";
const {push, goBack} = useRouter()
const {scrollTop} = useScroll()
const title = ref('')
@ -101,7 +107,7 @@ const selectCartId = ref(undefined)
const options = ref([{
text: '删除',
style: {
backgroundColor: '#f56c6c'
backgroundColor: '#EE6D46'
}
}])
@ -156,39 +162,29 @@ onLoad((option) => {
main.getAddressList(page.value)
})
const modalRef = ref()
const prepareData= ref({})
const handleAddressClick = async ({index}, data) => {
if (index == 0) {
uni.showModal({
title: '温馨提示',
content: '是否确认删除此地址?',
success: async (res) => {
if (res.confirm) {
uni.showLoading({
title: '删除中',
mask: true,
})
await getAddressDel(data)
uni.showToast({
title: "删除成功",
icon: "none",
duration: 2000
});
uni.hideLoading()
main.restAddress()
main.getAddressList(1)
} else if (res.cancel) {
}
}
});
}
/**
* 打开弹窗
*/
function showModal(data){
prepareData.value = data
unref(modalRef).show()
}
/**
* 删除地址
* @returns {Promise<void>}
*/
async function doDeleteRequest(){
await getAddressDel(prepareData.value)
await main.restAddress()
await main.getAddressList(1)
if(main.selectAddress && prepareData.value.id === main.selectAddress.id){
main.clearSelectAddress()
}
}
</script>
<style lang="scss">
@ -314,4 +310,18 @@ const handleAddressClick = async ({index}, data) => {
justify-content: center;
white-space: nowrap;
}
.addressList :deep(.uv-swipe-action-item__right__button__wrapper) {
position: relative;
&:before {
position: absolute;
content: '';
background: url("https://b2c-pro-static-dev.zkthink.com/static/images/delete_icon.png") no-repeat center center;
width: 50rpx;
height: 50rpx;
background-size: contain;
}
}
.addressList :deep(.uv-swipe-action-item__right__button__wrapper__text) {
visibility: hidden;
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<layout class="bargaining">
<view class="swiper">
<image src="@/static/images/kjzq.png" />
<image src="https://b2c-pro-static-dev.zkthink.com/static/images/kjzq.png" />
</view>
<blank size="15"></blank>
<container min>

View File

@ -1,12 +1,8 @@
<template>
<layout>
<uv-navbar
:fixed="false"
title="我的收藏"
left-arrow
@leftClick="goBack"
/>
<Header :scroll-top="scrollTop" header-area-bg="#fff" system-bar-area-bg="#fff">
我的收藏
</Header>
<view class="top-option">
<view />
<view
@ -17,64 +13,66 @@
</view>
</view>
<container>
<uv-swipe-action>
<space
direction="vertical"
fill
>
<template v-if="dataList.length>0">
<uv-checkbox-group
v-model="selectValues"
shape="circle"
activeColor="#ec6e47"
>
<view
class="select-row"
v-for="(item) in dataList"
:key="item.id"
>
<uv-checkbox
v-if="showManage"
:customStyle="{marginBottom: '8px'}"
:name="item.id"
/>
<card
style="width: 100%"
@click="handleRightSingleSelect(item)"
>
<uv-swipe-action-item
:disabled="showManage"
:options="options"
@click="handleOpenDelete(true, item)"
>
<goods
list
:data="item"
:storeName="item.storeName"
:price="item.price"
:stock="item.stock"
interval="true"
desc="3"
showAction="true"
surplus="200"
priceMode="primary"
@click=" push({url: '/pages/goodsDetail/goodsDetail'}, {data: {id: item.productId}})"
>
</goods>
</uv-swipe-action-item>
</card>
</view>
</uv-checkbox-group>
</template>
<Empty
:iconSrc="emptyIcon"
v-else
<view class="collect">
<uv-swipe-action>
<space
direction="vertical"
fill
>
您还没有收藏的商品~
</Empty>
</space>
</uv-swipe-action>
<template v-if="dataList.length>0">
<uv-checkbox-group
v-model="selectValues"
shape="circle"
activeColor="#ec6e47"
>
<view
class="select-row"
v-for="(item) in dataList"
:key="item.id"
>
<uv-checkbox
v-if="showManage"
:customStyle="{marginBottom: '8px'}"
:name="item.id"
/>
<card
style="width: 100%"
@click="handleRightSingleSelect(item)"
>
<uv-swipe-action-item
:disabled="showManage"
:options="options"
@click="handleOpenDelete(true, item)"
>
<goods
list
:data="item"
:storeName="item.storeName"
:price="item.price"
:stock="item.stock"
interval="true"
desc="3"
showAction="true"
surplus="200"
priceMode="primary"
@click=" push({url: '/pages/goodsDetail/goodsDetail'}, {data: {id: item.productId}})"
>
</goods>
</uv-swipe-action-item>
</card>
</view>
</uv-checkbox-group>
</template>
<Empty
:iconSrc="emptyCollectIcon"
v-else
>
您还没有收藏的商品~
</Empty>
</space>
</uv-swipe-action>
</view>
<view class="option-height"></view>
<!-- bar -->
@ -112,6 +110,8 @@
@confirm="toDelete"
@cancel="toCancelDelete"
></Modal>
<ReturnTop :scroll-top="scrollTop" />
</layout>
</template>
@ -123,20 +123,23 @@ import Modal from '@/components/Modal/index.vue'
import { usePage } from '@/hooks'
import Empty from "@/components/Empty/index.vue";
import emptyIcon from '@/static/icon/empty/收藏.png'
import {emptyCollectIcon} from "@/utils/images";
import { useRouter } from "@/hooks/useRouter";
import { useInterface } from "@/hooks/useInterface";
import ReturnTop from "@/components/ReturnTop/index.vue";
import { useScroll } from "@/hooks/useScroll";
import Header from "@/components/Header/index.vue";
const {goBack, push} = useRouter()
const {type, refresh, dataList} = usePage(collectPage)
const {toast} = useInterface();
const {scrollTop} = useScroll()
const options = ref([{
text: '删除',
style: {
backgroundColor: '#f56c6c'
backgroundColor: '#ee6d46'
}
}])
@ -319,4 +322,18 @@ onLoad(async (option) => {
}
}
}
.collect :deep(.uv-swipe-action-item__right__button__wrapper) {
position: relative;
&:before {
position: absolute;
content: '';
background: url("https://b2c-pro-static-dev.zkthink.com/static/images/delete_icon.png") no-repeat center center;
width: 50rpx;
height: 50rpx;
background-size: contain;
}
}
.collect :deep(.uv-swipe-action-item__right__button__wrapper__text) {
visibility: hidden;
}
</style>

View File

@ -203,6 +203,7 @@ const onSave = async () => {
if (actionType.value == 'select') {
push({url: '/pages/address/address'}, {data: {type: 'select'},type:'redirectTo'})
} else {
main.getAddressList(1)
goBack()
}
} catch (error) {

View File

@ -1,7 +1,7 @@
<template>
<layout>
<view class="swiper">
<image src="@/static/images/zkzq.png" />
<image src="https://b2c-pro-static-dev.zkthink.com/static/images/zkzq.png" />
</view>
<div class="time-bar">
<uv-tabs :current="active">

View File

@ -91,7 +91,7 @@ const goToProduct = (coupons) => {
.coupon-item {
width: 100%;
aspect-ratio: 682/176;
background: url("@/static/background/coupon-bg.png") no-repeat ;
background: url("https://b2c-pro-static-dev.zkthink.com/static/background/coupon-bg.png") no-repeat ;
background-size: 100%;
padding: 25rpx 60rpx;
box-sizing: border-box;

View File

@ -11,10 +11,13 @@ import { onLoad } from '@dcloudio/uni-app'
import { useRouter } from "@/hooks/useRouter";
const {goBack} = useRouter();
const {scrollTop} = useScroll()
import { useDiscountCoupon } from "@/pages/discountCoupon/index.utils";
import CouponItem from "@/pages/discountCoupon/components/CouponItem.vue";
import Empty from "@/components/Empty/index.vue"
import emptyIcon from '@/static/icon/empty/优惠券.png'
import { emptyCouponIcon } from "@/utils/images";
import ReturnTop from "@/components/ReturnTop/index.vue";
import { useScroll } from "@/hooks/useScroll";
const {
tabList,
@ -42,20 +45,21 @@ const {
<!-- coupon list -->
<view class="coupon-box">
<template v-if="!showEmpty">
<template v-for="item in couponList">
<view class="coupon-list" v-for="item in couponList">
<CouponItem
:coupons="item"
:tabType="tabCurrent"
/>
</template>
</view>
</template>
<Empty
:iconSrc="emptyIcon"
:iconSrc="emptyCouponIcon"
v-else
>
您暂时没有可使用的优惠券~
</Empty>
</view>
<ReturnTop :scroll-top="scrollTop" />
</view>
</template>
@ -76,6 +80,9 @@ const {
padding: 35rpx;
box-sizing: border-box;
width: 100%;
.coupon-list {
margin-bottom: 24rpx;
}
}
}

View File

@ -10,11 +10,12 @@
<div class="evaluate-item">
<view class="evaluate-label">商品评价</view>
<uv-rate
active-color="#EE6D46"
:count="5"
v-model="productScore"
></uv-rate>
</div>
<uv-line color="#E6E6E6"></uv-line>
<uv-line color="#EE6D46"></uv-line>
<view class="evaluate-content">
<uv-textarea
border="none"
@ -41,6 +42,7 @@
<div class="evaluate-item min">
<view class="evaluate-label">服务评价</view>
<uv-rate
active-color="#EE6D46"
:count="5"
v-model="serviceScore"
></uv-rate>
@ -93,7 +95,7 @@ const handleOrderComments = async () => {
icon: "none",
duration: 2000
});
push({url:'/pages/orderList/orderList'},{data:{type: 3}})
goBack()
}
}

View File

@ -1,7 +1,7 @@
<template>
<layout>
<view class="swiper">
<image src="@/static/images/flashKilling.png" />
<image src="https://b2c-pro-static-dev.zkthink.com/static/images/flashKilling.png" />
</view>
<div class="time-bar">
<uv-tabs v-model:active="active">

View File

@ -1,12 +1,8 @@
<template>
<layout>
<uv-navbar
:fixed="false"
title="我的足迹"
left-arrow
@leftClick="goBack"
/>
<Header :scroll-top="scrollTop" header-area-bg="#fff" system-bar-area-bg="#fff">
我的足迹
</Header>
<view class="top-option">
<view />
<view
@ -17,63 +13,65 @@
</view>
</view>
<container>
<uv-swipe-action>
<space
direction="vertical"
fill
>
<template v-if="dataList.length>0">
<uv-checkbox-group
v-model="selectValues"
shape="circle"
activeColor="#ec6e47"
>
<view
class="select-row"
v-for="(item) in dataList"
:key="item.id"
>
<uv-checkbox
v-if="showManage"
:customStyle="{marginBottom: '8px'}"
:name="item.id"
/>
<card
style="width: 100%"
@click="handleRightSingleSelect(item)"
>
<uv-swipe-action-item
:disabled="showManage"
:options="options"
@click="handleOpenDelete(true, item)"
>
<goods
list
:data="item"
:storeName="item.storeName"
:price="item.price"
:stock="item.stock"
interval="true"
desc="3"
showAction="true"
surplus="200"
priceMode="primary"
@click=" push({url: '/pages/goodsDetail/goodsDetail'}, {data: {id: item.productId}})"
>
</goods>
</uv-swipe-action-item>
</card>
</view>
</uv-checkbox-group>
</template>
<Empty
:iconSrc="emptyIcon"
v-else
<view class="footprint">
<uv-swipe-action>
<space
direction="vertical"
fill
>
您还没有浏览足迹~
</Empty>
</space>
</uv-swipe-action>
<template v-if="dataList.length>0">
<uv-checkbox-group
v-model="selectValues"
shape="circle"
activeColor="#ec6e47"
>
<view
class="select-row"
v-for="(item) in dataList"
:key="item.id"
>
<uv-checkbox
v-if="showManage"
:customStyle="{marginBottom: '8px'}"
:name="item.id"
/>
<card
style="width: 100%"
@click="handleRightSingleSelect(item)"
>
<uv-swipe-action-item
:disabled="showManage"
:options="options"
@click="handleOpenDelete(true, item)"
>
<goods
list
:data="item"
:storeName="item.storeName"
:price="item.price"
:stock="item.stock"
interval="true"
desc="3"
showAction="true"
surplus="200"
priceMode="primary"
@click=" push({url: '/pages/goodsDetail/goodsDetail'}, {data: {id: item.productId}})"
>
</goods>
</uv-swipe-action-item>
</card>
</view>
</uv-checkbox-group>
</template>
<Empty
:iconSrc="emptyCollectIcon"
v-else
>
您还没有浏览足迹~
</Empty>
</space>
</uv-swipe-action>
</view>
<view class="option-height"></view>
<!-- bar -->
<view
@ -111,6 +109,8 @@
@cancel="toCancelDelete"
></Modal>
</layout>
<ReturnTop :scroll-top="scrollTop" />
</template>
<script setup>
@ -121,10 +121,14 @@ import Modal from '@/components/Modal/index.vue'
import { usePage } from '@/hooks'
import Empty from "@/components/Empty/index.vue";
import emptyIcon from '@/static/icon/empty/收藏.png'
import {emptyCollectIcon} from "@/utils/images";
import { useRouter } from "@/hooks/useRouter";
import { useInterface } from "@/hooks/useInterface";
import { useScroll } from "@/hooks/useScroll";
import ReturnTop from "@/components/ReturnTop/index.vue";
import Header from "@/components/Header/index.vue";
const {scrollTop} = useScroll()
const {goBack, push} = useRouter()
const {type, refresh, dataList} = usePage(footprintPage)
@ -134,7 +138,7 @@ const {toast} = useInterface();
const options = ref([{
text: '删除',
style: {
backgroundColor: '#f56c6c'
backgroundColor: '#ee6d46'
}
}])
@ -320,4 +324,18 @@ onLoad(async (option) => {
}
}
}
.footprint :deep(.uv-swipe-action-item__right__button__wrapper) {
position: relative;
&:before {
position: absolute;
content: '';
background: url("https://b2c-pro-static-dev.zkthink.com/static/images/delete_icon.png") no-repeat center center;
width: 50rpx;
height: 50rpx;
background-size: contain;
}
}
.footprint :deep(.uv-swipe-action-item__right__button__wrapper__text) {
visibility: hidden;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<Header ref="headerRef"> 分类</Header>
<Header ref="headerRef" :scroll-top="scrollTop"> 分类</Header>
<view
class="goods-category"
:style="computeMainBoxStyle"
@ -72,9 +72,10 @@ import UvVtabsItem from "@/uni_modules/uv-vtabs/components/uv-vtabs-item/uv-vtab
import UvGrid from "@/uni_modules/uv-grid/components/uv-grid/uv-grid.vue";
import UvGridItem from "@/uni_modules/uv-grid/components/uv-grid-item/uv-grid-item.vue";
import UvGap from "@/uni_modules/uv-gap/components/uv-gap/uv-gap.vue";
import { useScroll } from "@/hooks/useScroll";
const {push} = useRouter()
const {scrollTop} = useScroll()
const headerRef = ref() //导航条
// 中心高度 100bh - 上导航栏 - h5底部高度

View File

@ -2,6 +2,7 @@
<layout class="goodsDetail">
<view :style="computedHeightStyle"></view>
<Header
:scroll-top="scrollTop"
ref="headerRef"
:propUp="false"
>
@ -189,7 +190,7 @@
>
<img
class="action-icon-img"
src="@/static/images/icon-kefu.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/icon-kefu.png"
/>
<text class="action-icon-label">客服</text>
</view>
@ -207,9 +208,9 @@
></uv-badge>
</view>
<img
<image
class="action-icon-img"
src="@/static/images/icon-gouwuche.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/icon-gouwuche.png"
/>
<text class="action-icon-label">购物车</text>
</view>
@ -222,12 +223,12 @@
<image
v-if="!storeInfo?.userCollect"
class="action-icon-img"
src="@/static/images/icon-shouceng.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/icon-shouceng.png"
/>
<image
v-if="storeInfo?.userCollect"
class="action-icon-img"
src="@/static/images/icon-shouceng-o.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/icon-shouceng-o.png"
/>
<text class="action-icon-label">收藏</text>
</view>
@ -247,7 +248,7 @@
></uv-button>
</view>
</view>
<ReturnTop :scroll-top="scrollTop" />
</layout>
</template>
@ -262,6 +263,7 @@ import Header from '@/components/Header/index.vue'
import GoodCouponSelect from "@/components/good-coupon-select/good-coupon-select.vue";
import UvIcon from "@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue";
import { useScroll } from "@/hooks/useScroll";
import ReturnTop from "@/components/ReturnTop/index.vue"
const {push, getParams, pushToTab, goBack} = useRouter();
const {toast} = useInterface()
@ -319,13 +321,15 @@ onLoad((options) => {
handleGetDetail(params.id)
handleGetCartCount(params.id)
})
useScroll()
const {scrollTop} = useScroll()
const goToService = () => {
toast({title: '😒敬请期待😒'})
}
const goToShopCart = () => {
pushToTab({url: '/pages/shoppingCart/shoppingCart'})
push({
url: '/pages/shoppingCartJump/shoppingCart'
})
}
const handleOpenSelect = (action) => {

View File

@ -51,7 +51,7 @@
</template>
<Empty
v-else
:iconSrc="emptyIcon"
:iconSrc="emptyCollectIcon"
>
这里空空如也~
</Empty>
@ -60,7 +60,10 @@
<!-- 加载完毕-->
<ListLoadOver v-if="loadend" />
</container>
</layout>
<ReturnTop :scroll-top="scrollTop" />
</template>
<script setup>
@ -72,9 +75,11 @@ import { useRouter } from "@/hooks/useRouter";
import Empty from "@/components/Empty/index.vue"
import ListLoadOver from "@/components/ListLoadOver/index.vue"
import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
import { emptyCollectIcon } from "@/utils/images";
import ReturnTop from "@/components/ReturnTop/index.vue"
import { useScroll } from "@/hooks/useScroll";
import emptyIcon from "@/static/icon/empty/收藏.png"
const {scrollTop} = useScroll()
const {getParams, goBack} = useRouter()
const {keyword, refresh, sid, couponId, dataList, loadend, loading, listEmpty} = usePage(getProductList)

View File

@ -1,11 +1,6 @@
<template>
<layout class="replys">
<uv-navbar
:fixed="false"
title="评价"
left-arrow
@leftClick="goBack"
/>
<Header :scroll-top="scrollTop">评价</Header>
<view class="replys">
<view class="tabs">
<view
class="item"
@ -29,21 +24,27 @@
/>
</view>
<Empty
:iconSrc="emptyIcon"
:iconSrc="emptyReply"
v-else
>
暂无评论~
</Empty>
</layout>
</view>
<ReturnTop :scroll-top="scrollTop" />
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { replyList } from '@/api/goods'
import Header from '@/components/Header/index.vue'
import Empty from '@/components/Empty/index.vue'
import { useRouter } from "@/hooks/useRouter";
import emptyIcon from '@/static/images/icon-dpj.png'
import { emptyReply } from "@/utils/images";
import ReturnTop from "@/components/ReturnTop/index.vue";
import { useScroll } from "@/hooks/useScroll";
const {scrollTop} = useScroll()
const replyListData = ref([])
const total = ref(0)
@ -131,4 +132,7 @@ onLoad((option) => {
}
}
}
page {
background: #ffffff;
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<layout>
<view class="swiper">
<image src="@/static/images/ptzq.png" />
<image src="https://b2c-pro-static-dev.zkthink.com/static/images/ptzq.png" />
</view>
<div class="groupBuy-top">
<container>

View File

@ -20,7 +20,7 @@
<swiper-item v-for="item in 10">
<view class="swiper-item">
<image
src="@/static/images/banner.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/banner.png"
mode="aspectFit"
/>
</view>
@ -40,13 +40,18 @@
.swiper {
height: 340rpx;
border-radius: 15rpx;
overflow: hidden;
.swiper-item {
height: 340rpx;
border-radius: 15rpx;
image {
width: 100%;
height: 100%;
border-radius: 15rpx;
}
}
}

View File

@ -1,7 +1,4 @@
import sp from "@/static/images/sp.png"
import pt from "@/static/images/pt.png"
import ms from "@/static/images/ms.png"
import kj from "@/static/images/kj.png"
import { sp, pt, ms, kj } from "@/utils/images";
export const menuList = [
{

View File

@ -8,6 +8,12 @@
<script setup>
import Recommend from "@/components/Recommend/index.vue";
import UvIcon from "@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue";
import { useRouter } from "@/hooks/useRouter";
const {push} = useRouter()
const goToProductMore = () => {
push({url: '/pages/goodsList/goodsList'})
}
</script>
<template>
@ -17,7 +23,7 @@ import UvIcon from "@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue";
<view class="left">
商品推荐
</view>
<view class="right flex flex-ai__center flex-jc__end">
<view class="right flex flex-ai__center flex-jc__end" @click="goToProductMore">
查看更多
<uv-icon name="arrow-right" color="#999" size="14" />
</view>

View File

@ -3,13 +3,14 @@
<view class="header-row">
<Header
:left-width="140"
:scroll-top="scrollTop"
@animation="handleHeaderAnimation"
>
<template #left>
<view class="logo-col">
<image
class="logo"
src="@/static/images/logo.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/logo.png"
alt=""
/>
</view>
@ -66,6 +67,7 @@
</template>
<!-- h5 tabbar 底部 -->
<view class="h5-tabbar-height"></view>
<ReturnTop :scroll-top="scrollTop" />
</view>
</template>
@ -84,6 +86,7 @@ import Live from './components/Live/index.vue'
import NewProduct from './components/NewProduct/index.vue'
import Seckill from './components/Seckill/index.vue'
import Recommend from "./components/Recommend/index.vue";
import ReturnTop from "@/components/ReturnTop/index.vue"
import UvIcon from "@/uni_modules/uv-icon/components/uv-icon/uv-icon.vue";
import { useScroll } from "@/hooks/useScroll";
@ -123,7 +126,7 @@ onLoad(() => {
doGetHomeData()
})
useScroll()
const {scrollTop} = useScroll()
</script>
@ -147,7 +150,7 @@ useScroll()
.search-col {
@include useFlex(flex-start, center);
@include usePadding(30, 15);
width: 320rpx;
width: 100%;
height: 60rpx;
border-radius: 50rpx;
background: $white-color;

View File

@ -1,7 +1,7 @@
<template>
<layout class="bargaining">
<view class="swiper">
<image src="@/static/images/kjzq.png" />
<image src="https://b2c-pro-static-dev.zkthink.com/static/images/kjzq.png" />
</view>
<blank size="15"></blank>
<container min>

View File

@ -6,7 +6,7 @@
@update: 2023-11-08 16:20
-->
<script setup>
import wechat from '@/static/icon/login/wechat.png'
import { wechat } from "@/utils/images";
import { useRouter } from "@/hooks/useRouter";
import { loginMethods } from "@/pages/login/index.data";
import { wxLogin } from "@/utils/wechatUtils";
@ -109,7 +109,7 @@ function toAgreement(type) {
<view class="main-box flex flex-jc__center">
<image
class="logo"
src="@/static/icon/logo.png"
src="https://b2c-pro-static-dev.zkthink.com/static/icon/logo.png"
/>
</view>
@ -157,7 +157,7 @@ function toAgreement(type) {
</template>
</view>
<!-- #ifdef MP-WEIXIN -->
<view
class="agreement-box"
:class="{'error-animation':isPrivacyError}"
@ -187,6 +187,7 @@ function toAgreement(type) {
</uv-checkbox>
</uv-checkbox-group>
</view>
<!-- #endif -->
</view>
</template>
@ -225,7 +226,8 @@ function toAgreement(type) {
align-items: center;
justify-content: center;
height: 88rpx;
font-size: 28rpx;
border-radius: 0;
.icon {
width: 40rpx;
height: 40rpx;

View File

@ -5,8 +5,8 @@
* @descriptionindex.data
* @update: 2023-11-08 16:35
* */
import wechat from '@/static/icon/login/wechat.png'
import phone from '@/static/icon/login/phone.png'
// import { wechat } from "@/utils/images";
import { phone } from "@/utils/images";
/**
* 登录方式

View File

@ -178,7 +178,7 @@ onBeforeUnmount(() => {
<view class="logo-box">
<image
class="logo"
src="@/static/icon/logo.png"
src="https://b2c-pro-static-dev.zkthink.com/static/icon/logo.png"
/>
</view>
@ -188,7 +188,7 @@ onBeforeUnmount(() => {
<view class="icon">
<image
class="icon"
src="@/static/icon/login/手机@2x.png"
src="https://b2c-pro-static-dev.zkthink.com/static/icon/login/手机@2x.png"
/>
</view>
<view class="area-code">
@ -228,7 +228,7 @@ onBeforeUnmount(() => {
<view class="icon">
<image
class="icon"
src="@/static/icon/login/验证码@2x.png"
src="https://b2c-pro-static-dev.zkthink.com/static/icon/login/验证码@2x.png"
/>
</view>
<view class="area-code">

View File

@ -19,7 +19,7 @@
<view class="swiper-item">
<image
class="image"
src="@/static/images/banner.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/banner.png"
mode="widthFix"
/>
</view>
@ -28,7 +28,7 @@
<view class="swiper-item">
<image
class="image"
src="@/static/images/banner.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/banner.png"
mode="widthFix"
/>
</view>
@ -37,7 +37,7 @@
<view class="swiper-item">
<image
class="image"
src="@/static/images/banner.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/banner.png"
mode="widthFix"
/>
</view>
@ -82,7 +82,7 @@
</view>
<Empty
v-else
:iconSrc="emptyIcon"
:iconSrc="emptyCollectIcon"
>
这里空空如也~
</Empty>
@ -103,7 +103,7 @@ import { usePage } from '@/hooks'
import Goods from "@/components/goodsComponents/Goods.vue"
import ListLoadOver from "@/components/ListLoadOver/index.vue";
import ListLoadLoading from "@/components/ListLoadLoading/index.vue";
import emptyIcon from "@/static/icon/empty/收藏.png";
import {emptyCollectIcon} from "@/utils/images";
import Empty from "@/components/Empty/index.vue";
const {news, refresh, dataList, loading, loadend, listEmpty} = usePage(getProductList)

View File

@ -11,7 +11,7 @@
<view class="background">
<image
class="image"
src="@/static/images/order-info-bg.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/order-info-bg.png"
mode="widthFix"
/>
</view>
@ -23,12 +23,12 @@
>
<!-- <image
class="image"
src="@/static/images/kjzq.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/kjzq.png"
/> -->
<view>{{ orderInfoStatusMsg }}</view>
<view>{{ orderInfoData._status._title }}</view>
</view>
<view class="order-date">
{{ orderInfoData._status._msg }}
{{orderInfoData._status._type === "2"?`${remainTimeStr}`:orderInfoData._status._msg }}
</view>
</view>
<view class="address noBorder">
@ -36,7 +36,7 @@
<image
class="image"
src="@/static/images/icon-location.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/icon-location.png"
/>
</view>
<view class="address-main">
@ -58,7 +58,7 @@
<view class="order-logo">
<image
class="image"
src="@/static/images/flashKilling.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/flashKilling.png"
alt=""
/>
</view>
@ -142,7 +142,7 @@
</view>
<view
class="info-cell"
v-if="orderInfoData.status > 0"
v-if="orderInfoData.status > 0 && orderInfoData.payTime"
>
<view class="info-cell-label">
付款时间
@ -210,7 +210,7 @@
<view class="order-actions-btns">
<view
class="order-actions-delete"
@tap="handleCancel"
@tap="showModal(1)"
>
取消订单
</view>
@ -255,7 +255,7 @@
</view>
<view
class="order-actions-primary"
@tap="handleOrderTake"
@tap="showModal(2)"
>
确认收货
</view>
@ -296,7 +296,7 @@
<view class="order-actions-btns">
<view
class="order-actions-delete"
@tap="handleDelete"
@tap="showModal(0)"
>
删除订单
</view>
@ -357,12 +357,16 @@
<!-- 支付弹窗 -->
<PayPopup
ref="payPopupRef"
@confrim="paySucess"
@confrim="paySuccess"
/>
<Modal ref="modalRef" :content="modalTitle" @confirm="confirmModal" />
</template>
<script setup>
import { ref, unref } from 'vue'
import { computed, ref, unref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { orderCancel, orderDelete, orderExpress, orderInfo, orderTake } from '@/api/order'
import { orderReStatus } from '@/config'
@ -370,14 +374,20 @@ import { useRouter } from "@/hooks/useRouter";
import { useShearPlate } from "@/hooks/useShearPlate";
import { useGlobalProperties } from "@/hooks";
import PayPopup from "@/components/PayPopup/index.vue";
import Modal from "@/components/Modal/index.vue";
import { useInterface } from "@/hooks/useInterface";
import {formatRemainTime} from "@/utils/utils";
const {$timeFormat} = useGlobalProperties()
const {getParams, push, goBack} = useRouter()
const {toast} = useInterface();
const orderInfoData = ref(null)
const orderInfoStatusMsg = ref('')
const expressData = ref(null)
const remainTimeStr = ref('')
const {setData} = useShearPlate();
@ -387,7 +397,11 @@ const handleOrderInfo = async (option) => {
orderInfoData.value = res
res.status = res.paid === 1 && res.status === 0 ? 99 : res.status
handleMsg(res.status)
if (res._status._type > 1) {
if (parseInt(res._status._type) > 1) {
console.log(parseInt(res._status._type),'parseInt(res._status._type)')
if(parseInt(res._status._type) === 2){
remainTimeStr.value = formatRemainTime(res._status._payRemainTime)
}
const express = await orderExpress({
orderCode: orderInfoData.value.orderId,
shipperCode: orderInfoData.value.deliverySn,
@ -398,41 +412,10 @@ const handleOrderInfo = async (option) => {
}
const handleOrderTake = async () => {
uni.showModal({
title: '提示',
content: '确认收货',
success: async (res) => {
if (res.confirm) {
let option = {
uni: orderInfoData.value.orderId,
}
const res = await orderTake(option)
uni.showToast({
title: '收货成功',
duration: 2000
});
handleOrderInfo({
key: option.uni
})
} else if (res.cancel) {
}
}
});
}
const handlePay = () => {
openPay(orderInfoData.value.orderId)
// push({url: '/pages/selectPlay/selectPlay'}, {
// data: {
// key: orderInfoData.value.unique,
// orderId: orderInfoData.value.orderId,
// }
// })
}
// 返回列表
@ -454,7 +437,8 @@ const goList = ()=>{
push({url: '/pages/orderList/orderList'}, {
data: {
type: status
}
},
timeout:2000
})
}
@ -463,7 +447,8 @@ const toEvaluate = (item) => {
push({url: '/pages/evaluate/evaluate'}, {
data: {
unique: item.unique,
}
},
type:'redirectTo'
})
}
@ -482,50 +467,59 @@ const handleMsg = (status) => {
}
const handleDelete = async () => {
uni.showModal({
title: '提示',
content: '确认删除订单',
success: async (res) => {
if (res.confirm) {
await orderDelete({
uni: orderInfoData.value.orderId
})
uni.showToast({
title: '已删除',
duration: 2000
});
setTimeout(()=>{
goList()
},2000)
} else if (res.cancel) {
}
}
});
const modalRef = ref()
const modalType = ref(0) // 0删除 1取消 2确认收货
const modalTitle = computed(()=>{
const tipsArr = ['确认删除订单吗?','确认取消订单吗?','确认要确认收货吗?']
return tipsArr[modalType.value]
})
/**
* 打开弹窗
* @param {number} type 0删除记录 1撤销申请 2确认收货
*/
function showModal(type){
modalType.value = type
unref(modalRef).show()
}
const handleCancel = async () => {
uni.showModal({
title: '提示',
content: '确认取消订单',
success: async (res) => {
if (res.confirm) {
await orderCancel({
id: orderInfoData.value.orderId
})
uni.showToast({
title: '已取消',
duration: 2000
});
setTimeout(()=>{
goList()
},2000)
} else if (res.cancel) {
}
}
});
/**
* 确认弹窗
*/
function confirmModal(){
const funcArr = [doDeleteRequest,doCancelRequest,doTakeRequest]
funcArr[modalType.value]()
}
async function doDeleteRequest(){
await orderDelete({
uni: orderInfoData.value.orderId
})
toast({title: '删除成功'});
goList()
}
async function doCancelRequest(){
await orderCancel({
id: orderInfoData.value.orderId
})
toast({title: '取消成功'});
goList()
}
async function doTakeRequest(){
let option = {
uni: orderInfoData.value.orderId,
}
await orderTake(option)
toast({title: '收货成功'});
await handleOrderInfo({
key: option.uni
})
}
// ============================== 支付相关 ===============================
const payPopupRef = ref()
@ -579,16 +573,16 @@ onLoad((options) => {
margin-right: 10rpx;
}
&.order-status-0,&.order-status--1 {
background-image: url("../../static/images/icon-order-info-1.png");
&.order-status-0,&.order-status--1,&.order-status-4,&.order-status-5,&.order-status-6,&.order-status-7 {
background-image: url("https://b2c-pro-static-dev.zkthink.com/static/images/icon-order-info-1.png");
}
&.order-status-1, &.order-status-99 {
background-image: url("../../static/images/icon-order-info-2.png");
background-image: url("https://b2c-pro-static-dev.zkthink.com/static/images/icon-order-info-2.png");
}
&.order-status-2, &.order-status-3 {
background-image: url("../../static/images/icon-order-info-4.png");
background-image: url("https://b2c-pro-static-dev.zkthink.com/static/images/icon-order-info-4.png");
}
}

View File

@ -1,68 +1,68 @@
<template>
<view>
<layout>
<uv-sticky
bgColor="#fff"
customNavHeight="0"
<uv-sticky
bgColor="#fff"
customNavHeight="0"
>
<uv-navbar
:fixed="false"
:title="title"
@leftClick="goBack"
/>
<uv-tabs
:list="navList"
@click="click"
lineColor="#f56c6c"
:current="actionType"
>
<uv-navbar
:fixed="false"
:title="title"
@leftClick="goBack"
/>
<uv-tabs
:list="navList"
@click="click"
lineColor="#f56c6c"
:current="actionType"
>
</uv-tabs>
</uv-sticky>
</uv-tabs>
</uv-sticky>
<view class="orderList">
<template v-if="!listEmpty">
<order
:data="item"
v-for="(item, index) in dataList"
:key="actionType + '_' + index"
@refresh="handleRefresh"
@pay="openPay"
/>
</template>
<Empty
:iconSrc="emptyIcon"
v-else
>
您还没有相关订单~
</Empty>
<!-- 加载中 -->
<ListLoadLoading v-if="loading" />
<!-- 加载完毕-->
<ListLoadOver v-if="loadend" />
</view>
</layout>
<view class="orderList">
<template v-if="!listEmpty">
<order
:data="item"
v-for="(item, index) in dataList"
:key="actionType + '_' + index"
@refresh="handleRefresh"
@pay="openPay"
/>
</template>
<Empty
:iconSrc="emptyOrderIcon"
v-else
>
您还没有相关订单~
</Empty>
<!-- 加载中 -->
<ListLoadLoading v-if="loading" />
<!-- 加载完毕-->
<ListLoadOver v-if="loadend" />
</view>
<!-- 支付弹窗 -->
<PayPopup
ref="payPopupRef"
@confirm="paySuccess"
/>
</view>
<ReturnTop :scroll-top="scrollTop" />
</template>
<script setup>
import { computed, ref, unref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { onLoad, onPageScroll } from '@dcloudio/uni-app'
import { orderList } from '@/api/order'
import { useRouter } from "@/hooks/useRouter";
import ListLoadOver from "@/components/ListLoadOver/index.vue"
import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
import Empty from '@/components/Empty/index.vue'
import emptyIcon from '@/static/icon/empty/订单.png'
import { emptyOrderIcon } from "@/utils/images";
import PayPopup from '@/components/PayPopup/index.vue'
import { usePage } from "@/hooks";
import Header from "@/components/Header/index.vue"
import { getProductList } from "@/api/product";
import ReturnTop from "@/components/ReturnTop/index.vue";
import { useScroll } from "@/hooks/useScroll";
const {scrollTop} = useScroll()
const {type, refresh, dataList, loadend, loading, listEmpty} = usePage(orderList)
const {getParams, goBack, push} = useRouter()
@ -82,9 +82,9 @@ const navList = ref([
// { name: "退款", value: 7, },
])
const title = computed(()=>{
const find = navList.value.find(item=>item.value === type.value);
return find?`${find.name}订单`:'订单'
const title = computed(() => {
const find = navList.value.find(item => item.value === type.value);
return find ? `${ find.name }订单` : '订单'
})
@ -119,7 +119,7 @@ function openPay(orderId) {
}
function paySuccess() {
push({url: '/pages/payStatus/index'},{})
push({url: '/pages/payStatus/index'}, {})
}
@ -135,6 +135,10 @@ onLoad((options) => {
})
onPageScroll((e)=>{
})
</script>
<style lang="scss">

View File

@ -7,7 +7,7 @@
-->
<script setup>
import { useRouter } from "@/hooks/useRouter";
import { computed, ref, unref } from "vue";
import { computed, ref, unref,nextTick } from "vue";
import { onLoad, onPageScroll, onReachBottom } from "@dcloudio/uni-app";
import { checkPay } from "@/api/order";
import { CacheKey } from "@/utils/config";
@ -15,32 +15,32 @@ import Header from '@/components/Header/index.vue'
import Recommend from '@/components/Recommend/index.vue'
import { useInterface } from "@/hooks/useInterface";
import { useScroll } from "@/hooks/useScroll";
import Modal from "@/components/Modal/index.vue";
import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
import { lazyLoading, payError, paySuccess } from "@/utils/images";
const {getParams, goBack, push, pushToTab} = useRouter()
const {loading,hideLoading} = useInterface()
const type = ref(0) // 支付状态 0支付中 1支付成功 2支付失败
useScroll()
const {scrollTop} = useScroll()
const title = computed(() => {
if (type.value === 0) return '支付中...'
if (type.value === 0) return '查询中...'
if (type.value === 1) return '支付成功'
if (type.value === 2) return '支付失败'
})
const routerParams = ref({})
const modalRef = ref()
/**
* 去订单列表
* @param type 0 待支付 1 待发货
* 打开弹窗
*/
function toOrderList(type) {
push({url: '/pages/orderList/orderList'}, {data: {type}, type: 'reLaunch'})
function showModal(){
unref(modalRef).show()
}
function toBackHome() {
pushToTab({url: '/pages/index/index'})
}
const retryTime = ref(3)
const retryTime = ref(3) // 重试次数
/**
* 查询服务端支付状态
@ -72,10 +72,28 @@ async function queryOrderStatus() {
} finally {
hideLoading()
}
}, 1000)
}, 500)
}
/**
* 去订单列表
* @param type 0 待支付 1 待发货
*/
function toOrderList(type) {
push({url: '/pages/orderList/orderList'}, {data: {type}, type: 'reLaunch'})
}
/**
* 返回首页
*/
function toBackHome() {
pushToTab({url: '/pages/index/index'})
}
const recommendRef = ref(null)
onReachBottom(() => {
unref(recommendRef).onReachBottom && unref(recommendRef).onReachBottom();
})
@ -83,43 +101,41 @@ onReachBottom(() => {
onLoad(async (options) => {
// H5 和 APP 需要弹窗去确认
// #ifdef H5
uni.showModal({
content: '请确认支付是否完成',
success: async () => {
await queryOrderStatus()
}
await nextTick(()=>{
showModal()
})
// #endif
// #ifndef H5
await queryOrderStatus()
// #endif
})
</script>
<template>
<view class="pay-status">
<Header>
<Header :scroll-top="scrollTop">
{{ title }}
</Header>
<view class="status-main flex flex-column flex-ai__center">
<image
class="icon"
v-if="Number(type)===2"
src="@/static/icon/pay/pay-error.png"
/>
<image
class="icon col-icon"
v-else-if="Number(type)===0"
src="@/static/icon/logo.png"
v-if="Number(type)===0"
:src="lazyLoading"
/>
<image
class="icon"
v-else
src="@/static/icon/pay/pay-success.png"
v-if="Number(type)===1"
:src="paySuccess"
/>
<view class="text">
<image
class="icon"
v-if="Number(type)===2"
:src="payError"
/>
<view class="text" v-if="[1,2].includes(Number(type))">
{{ title }}
</view>
<ListLoadLoading v-else :show-line="false" text="查询中..." />
</view>
<view class="button-group flex flex-ai__center flex-jc__center">
<view
@ -146,6 +162,7 @@ onLoad(async (options) => {
</view>
<!-- 商品推荐 -->
<Recommend ref="recommendRef" />
<Modal ref="modalRef" content="请确认支付是否完成?" @confirm="queryOrderStatus" @cancel="queryOrderStatus" />
</view>
</template>
@ -159,17 +176,19 @@ onLoad(async (options) => {
.status-main {
@include usePadding(0, 130);
width: 100%;
font-size:36rpx;
.icon {
width: 170rpx;
height: 170rpx;
margin-bottom: 20rpx;
margin-bottom: 30rpx;
}
.col-icon {
width: 240rpx;
height: 120rpx;
}
}
.button-group {

View File

@ -11,7 +11,7 @@
<view class="background">
<image
class="image"
src="@/static/images/refund-order-bg.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/refund-order-bg.png"
mode="widthFix"
/>
</view>
@ -23,15 +23,15 @@
{{refundOrderStatus[orderInfoData.state]}}
</view>
</view>
<view class="order-date">
还剩1天20小时自动确认
<view class="order-date" v-if="parseInt(orderInfoData.remainTime) > 0 && ![3,4].includes(orderInfoData.state)">
还剩{{remainTimeStr}}自动确认
</view>
</view>
<!-- <view class="address noBorder">-->
<!-- <view class="address-icon">-->
<!-- <image-->
<!-- class="image"-->
<!-- src="@/static/images/icon-location.png"-->
<!-- src="https://b2c-pro-static-dev.zkthink.com/static/images/icon-location.png"-->
<!-- />-->
<!-- </view>-->
<!-- <view class="address-main">-->
@ -152,7 +152,7 @@
退款金额
</view>
<view class="info-cell-value">
¥{{ orderInfoData.refundAmount }}
¥{{ orderInfoData.refundAmount.toFixed(2) }}
</view>
</view>
@ -243,14 +243,14 @@
<view class="order-actions-btns">
<view
class="order-actions-default"
@tap="handleDelete"
@tap="showModal(0)"
v-if="[3,4].includes(orderInfoData.state)"
>
删除记录
</view>
<view
class="order-actions-default"
@tap="handleRevoke"
@tap="showModal(1)"
v-if="[0,1].includes(orderInfoData.state)"
>
撤销申请
@ -274,12 +274,14 @@
</view>
</layout>
<Modal ref="modalRef" :content="modalTitle" @confirm="confirmModal" />
</template>
<script setup>
import { ref } from 'vue'
import { computed, ref, unref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useMainStore } from '@/store/store'
import { formatDate } from '@/utils/utils'
import {
orderCancel,
checkForAfterSalesInfo,
@ -291,6 +293,8 @@ import {
import { orderReStatus } from '@/config'
import { useRouter } from "@/hooks/useRouter";
import {useGlobalProperties} from "@/hooks";
import { formatRemainTime } from '@/utils/utils'
import Modal from "@/components/Modal/index.vue";
const {$timeFormat} = useGlobalProperties()
const {getParams,push,goBack} = useRouter()
@ -298,7 +302,9 @@ const {getParams,push,goBack} = useRouter()
const orderInfoData = ref(null)
const orderInfoStatusMsg = ref('')
const expressData = ref(null)
const id = ref(0)
const orderId = ref(0)
const remainTimeStr = ref('')
const refundOrderStatus = ref({
0: '请耐心等待平台审核',
1: '平台已同意退货申请,请尽早退货',
@ -312,54 +318,67 @@ const refundOrderStatus = ref({
const handleOrderInfo = async (option) => {
const res = await checkForAfterSalesInfo(option)
orderInfoData.value = res
remainTimeStr.value = formatRemainTime(orderInfoData.value.remainTime)
}
// 删除记录
const handleDelete = async () => {
uni.showModal({
title: '提示',
content: '确认删除记录',
success: async (res) => {
if (res.confirm) {
await afterSalesOrderDelete({
id: orderId.value,
orderCode: orderInfoData.value.orderId
})
uni.showToast({
title: '已删除',
duration: 2000
});
setTimeout(()=>{
toRefundList()
},2000)
} else if (res.cancel) {
}
}
});
const modalRef = ref()
const modalType = ref(0) // 0删除记录 1撤销申请
const modalTitle = computed(()=>{
const tipsArr = ['确认删除记录吗?','确认撤销申请吗?']
return tipsArr[modalType.value]
})
/**
* 打开弹窗
* @param {number} type 0删除记录 1撤销申请
*/
function showModal(type){
modalType.value = type
unref(modalRef).show()
}
// 撤销申请
const handleRevoke = async () => {
uni.showModal({
title: '提示',
content: '确认撤销申请吗',
success: async (res) => {
if (res.confirm) {
await afterSalesOrderRevoke({
id: orderId.value,
key: orderInfoData.value.orderId
})
uni.showToast({
title: '已撤销',
duration: 2000
});
setTimeout(()=>{
toRefundList()
},2000)
} else if (res.cancel) {
}
}
/**
* 确认弹窗
*/
function confirmModal(){
const funcArr = [doDeleteRequest,doRevoke]
funcArr[modalType.value]()
}
/**
* 确认删除
* @returns {Promise<void>}
*/
async function doDeleteRequest(){
await afterSalesOrderDelete({
id: id.value,
orderCode: orderInfoData.value.orderId
})
uni.showToast({
title: '已删除',
duration: 2000
});
setTimeout(()=>{
toRefundList()
},2000)
}
/**
* 确认撤销
* @returns {Promise<void>}
*/
async function doRevoke(){
await afterSalesOrderRevoke({
id: id.value,
key: orderInfoData.value.orderId
})
uni.showToast({
title: '已撤销',
duration: 2000
});
setTimeout(()=>{
toRefundList()
},2000)
}
// 跳转列表
@ -386,14 +405,15 @@ const toRefund = () => {
goods: orderInfoData.value.cartInfo.map(v=>{
return v.productAttrUnique
}).toString(),
id: orderInfoData.value.id
id: orderId.value
}
})
}
onLoad((options) => {
const params = getParams(options)
orderId.value = params.id
id.value = params.id
orderId.value = params.orderId
handleOrderInfo({
key: params.id
})
@ -431,10 +451,10 @@ onLoad((options) => {
background-position: left center;
background-repeat: no-repeat;
&.order-status-0,&.order-status-1,&.order-status-2,&.order-status-5{
background-image: url("../../static/images/icon-order-info-5.png");
background-image: url("https://b2c-pro-static-dev.zkthink.com/static/images/icon-order-info-5.png");
}
&.order-status-3,&.order-status-4{
background-image: url("../../static/images/icon-order-info-4.png");
background-image: url("https://b2c-pro-static-dev.zkthink.com/static/images/icon-order-info-4.png");
}
.image {
width: 40rpx;

View File

@ -29,13 +29,16 @@
</view>
<Empty
v-else
:iconSrc="emptyIcon"
:iconSrc="emptyOrderIcon"
></Empty>
<!-- 加载中 -->
<ListLoadLoading v-if="loading" />
<!-- 加载完毕-->
<ListLoadOver v-if="loadend" />
</layout>
<ReturnTop :scroll-top="scrollTop" />
</template>
<script setup>
@ -43,9 +46,15 @@ import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { orderList, storeAfterSalesList } from '@/api/order'
import { useRouter } from "@/hooks/useRouter";
import emptyIcon from "@/static/icon/empty/订单.png"
import {emptyOrderIcon} from "@/utils/images";
import Empty from "@/components/Empty/index.vue"
import { usePage } from "@/hooks";
import ReturnTop from "@/components/ReturnTop/index.vue";
import ListLoadOver from "@/components/ListLoadOver/index.vue"
import ListLoadLoading from "@/components/ListLoadLoading/index.vue"
import { useScroll } from "@/hooks/useScroll";
const {scrollTop} = useScroll()
const {type, refresh, dataList, loadend, loading, listEmpty} = usePage(storeAfterSalesList)

View File

@ -27,18 +27,18 @@
<label>热门搜索</label>
<image
class="seeIcon hotSearchListSee-icon"
:src="!hideHotFlag?'../../static/images/see.png':'../../static/images/notSee.png'"
:src="!hideHotFlag?'https://b2c-pro-static-dev.zkthink.com/static/images/see.png':'https://b2c-pro-static-dev.zkthink.com/static/images/notSee.png'"
@click="hideHotFlag = !hideHotFlag"
/>
</view>
<viewhot
<view
class="hot-flex-list"
v-if="!hideHotFlag"
>
<view
v-for="(item, index) in hotSearchList"
v-for="(item,index) in hotSearchList"
:key="index"
class="historySearDel-box flex-items-plus mar-right-30"
class="historySearDel-box flex-items-plus"
>
<view
class="boxContent"
@ -46,7 +46,7 @@
>{{ item }}
</view>
</view>
</viewhot>
</view>
<view
v-else
class="notSeeContent"
@ -59,13 +59,13 @@
<label class="title">历史搜索</label>
<image
class="historyDel-icon"
@click="delSearchHistory(1)"
src="../../static/images/delete.png"
@click="showModal(0)"
src="https://b2c-pro-static-dev.zkthink.com/static/images/delete.png"
/>
</view>
<view class="historySear-box hot-flex-list">
<view
v-for="item in historyList"
v-for="(item,index) in historyList"
:key="index"
class="historySearDel-box flex-items-plus"
>
@ -74,27 +74,19 @@
@click="handleClickHistoryOrHot(item)"
>{{ item }}
</view>
<!-- <label class="ertical-lines">|</label>-->
<!-- <view-->
<!-- class="historyIconBox"-->
<!-- @click="delSearchHistory(2,item.searchId)"-->
<!-- >-->
<!-- <image-->
<!-- class="historySearDel-icon text-align"-->
<!-- src="https://ceres.zkthink.com/static/img/index/historySearDel_icon.png"-->
<!-- />-->
<!-- </view>-->
</view>
</view>
</view>
</layout>
<Modal ref="modalRef" :content="modalTitle" @confirm="confirmModal" />
</template>
<script setup>
import { ref } from 'vue';
import { computed, ref, unref } from 'vue';
import { useRouter } from "@/hooks/useRouter";
import { onShow } from '@dcloudio/uni-app'
import { hotSearch, historySearch, clearHistorySearch } from "@/api/product";
import Modal from "@/components/Modal/index.vue";
const {push, goBack} = useRouter()
const searchRef = ref();
@ -103,9 +95,6 @@ const keyword = ref('');
const hotSearchList = ref([])
const getHotKeywordList = async () => {
hotSearchList.value = await hotSearch(0, 10)
// return request(API.SelectHotSearch, {}, 'GET').then(res => {
// hotSearchList.value = res.data
// })
}
@ -116,39 +105,42 @@ const getHistoryKeywordList = async () => {
historyList.value = historData.slice(0, 20)
}
// const onSearch = () => {
// // refresh()
// push({url: '/pages/goodsList/goodsList'}, {
// data: {
// keyword: keyword.value
// }
// })
// }
const modalRef = ref()
const modalType = ref(0) // 0删除记录 1撤销申请
const modalTitle = computed(()=>{
const tipsArr = ['您确定要清空搜索记录吗?','您确定要删除这一条记录吗?']
return tipsArr[modalType.value]
})
/**
* 删除历史记录
* @param status 1全部 2单条
* @param searchId
* 打开弹窗
* @param {number} type 0删除记录 1撤销申请
*/
function delSearchHistory(status = 1, searchId = undefined) {
const tips = status === 1 ? '您确定要清空搜索记录吗?' : '您确定要删除这一条记录吗?'
uni.showModal({
title: '温馨提示',
content: tips,
success: async (res) => {
if (res.confirm) {
await clearHistorySearch()
uni.showToast({
title: '已清空',
duration: 2000
});
await getHistoryKeywordList()
} else if (res.cancel) {
}
}
})
function showModal(type){
modalType.value = type
console.log(modalRef.value)
unref(modalRef).show()
}
/**
* 确认弹窗
*/
function confirmModal(){
const funcArr = [doClearAllRequest]
funcArr[modalType.value]()
}
/**
* 清空所有
* @returns {Promise<void>}
*/
async function doClearAllRequest(){
await clearHistorySearch()
await getHistoryKeywordList()
}
const keywordData = ref('')
function handleClickHistoryOrHot(key) {
keywordData.value = key
@ -174,7 +166,7 @@ const onCancel = () => {
}
onShow(() => {
Promise.all(getHotKeywordList(), getHistoryKeywordList())
Promise.all([getHotKeywordList(), getHistoryKeywordList()])
})
@ -286,17 +278,20 @@ onShow(() => {
font-size: 28rpx;
}
}
.hot-flex-list{
gap:20rpx;
}
.historySearDel-box {
height: 54rpx;
line-height: 54rpx;
margin: 15rpx 15rpx;
background-color: #F1F1F1;
text-align: center;
overflow: hidden;
display: flex;
justify-content: space-between;
margin-right: 30rpx;
.boxContent {
font-size: 24rpx;
padding: 0 30rpx;

View File

@ -7,7 +7,7 @@
-->
<script setup>
import Empty from '@/components/Empty/index.vue'
import emptyIcon from "@/static/icon/empty/购物车.png";
import { emptyCartIcon } from "@/utils/images";
import { useRouter } from "@/hooks/useRouter";
const {pushToTab} = useRouter()
@ -16,7 +16,7 @@ const {pushToTab} = useRouter()
<template>
<Empty
:iconSrc="emptyIcon"
:iconSrc="emptyCartIcon"
>
<template #default>
购物车里空空如也

View File

@ -17,6 +17,11 @@ export const settleFields = [
field: 'couponPrice',
prefix: '-¥'
},
{
label: '运费',
field: 'storePostage',
prefix: '¥'
},
{
label: '总计',
field: 'totalPrice',

View File

@ -246,13 +246,18 @@ export function useCartNumber(options) {
*/
function handleCartNumberChange(item, type = 'plus') {
if (type === 'plus') {
// +
if (item.cartNum + 1 > item.trueStock) return toast({title: '超出库存啦~'})
item.cartNum += 1
if (item.cartNum + 1 > item.trueStock){
item.cartNum = item.trueStock
} else{
item.cartNum += 1
}
} else {
// -
if (item.cartNum - 1 <= 0) return toast({title: '至少选一件哦~'})
item.cartNum -= 1
if (item.cartNum <= 1){
item.cartNum = 1
} else {
item.cartNum -= 1
}
}
doCartNumberChangeRequest(item)
}

View File

@ -1,5 +1,6 @@
<template>
<Header
:scroll-top="scrollTop"
system-bar-area-bg="#fff"
header-area-bg="#fff"
bg-change-by-scroll
@ -74,12 +75,13 @@
>
<view
class="button"
:class="item.cartNum <= 1 && 'disabled'"
@click="handleCartNumberChange(item,'minus')"
>
<uv-icon
name="minus"
color="#333"
size="12"
size="24rpx"
></uv-icon>
</view>
<view class="input">
@ -92,12 +94,13 @@
</view>
<view
class="button"
:class="item.cartNum >= item.trueStock && 'disabled'"
@click="handleCartNumberChange(item,'plus')"
>
<uv-icon
name="plus"
color="#333"
size="12"
size="24rpx"
></uv-icon>
</view>
</view>
@ -187,6 +190,7 @@
content="确认要删除这些购物车数据吗?"
@confirm="doDelete"
/>
<ReturnTop :scroll-top="scrollTop" />
</template>
<script setup>
@ -201,6 +205,8 @@ import Header from "@/components/Header/index.vue"
import { onHide, onPageScroll, onReachBottom } from "@dcloudio/uni-app";
import Recommend from "@/components/Recommend/index.vue";
import { useScroll } from "@/hooks/useScroll";
import ReturnTop from "@/components/ReturnTop/index.vue"
const modalRef = ref() // 删除弹窗
const goodsAttrSelectRef = ref() // 更改sku
@ -246,7 +252,7 @@ onHide(() => {
goodsAttrSelectRef.value?.close()
})
useScroll()
const {scrollTop} = useScroll()
</script>
<style lang="scss">
@ -311,7 +317,7 @@ useScroll()
font-size: 24rpx;
.input {
width: 120rpx;
width: 70rpx;
input {
@ -323,19 +329,28 @@ useScroll()
.button {
font-size: 32rpx;
width: 34rpx;
width: 40rpx;
aspect-ratio: 1/1;
border-radius: 5rpx;
border: 2rpx solid #cccccc;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
transition: all .3s;
border: 1px solid #999999;
&:active {
scale: 1.2;
}
&.disabled{
border-color: #dddddd;
:deep(.uv-icon__icon){
color: #dddddd !important;
}
&:active {
scale: 1;
}
}
}
}
}
@ -356,7 +371,7 @@ useScroll()
&.show {
@include usePadding(40, 10);
border-top: 1rpx solid #E6E6E6;
height: 230rpx;
height: 260rpx;
}
}

View File

@ -0,0 +1,419 @@
<template>
<Header
:scroll-top="scrollTop"
system-bar-area-bg="#fff"
header-area-bg="#fff"
bg-change-by-scroll
>
购物车
</Header>
<!-- have data -->
<view v-if="!showEmpty">
<!-- manage row -->
<view class="cart-manage">
<view @click="manage=!manage">
{{ manageStr }}
</view>
</view>
<!-- cart body box-->
<uv-checkbox-group
v-model="shoppingSelect"
shape="circle"
activeColor="#ee6d46"
@change="handleSingleSelect"
>
<card class="shopping-checkbox">
<!-- 购物车信息 -->
<view
v-for="(item) in cartList"
:key="item.id"
class="shopping-item"
>
<uv-checkbox
:name="item.id"
/>
<view class="good">
<Goods
row
imgWidth="200rpx"
info-padding="0 0 0 40rpx"
:goods="item.productInfo"
>
<template #options>
<view class="goods-options">
<!-- sku select -->
<view class="sku-row flex">
<view
class="sku-info flex flex-jc__sb flex-ai__center"
@click.stop="handleOpenSkuSelect(item,goodsAttrSelectRef)"
>
<view class="info">
{{ item.productInfo && item.productInfo.attrInfo && item.productInfo.attrInfo.sku }}
</view>
<uv-icon
class="icon"
name="arrow-down"
color="#ccc"
size="12"
/>
</view>
</view>
<!-- bottom -->
<view class="price-row flex flex-ai__center flex-jc__sb">
<!-- price -->
<view class="price-box flex flex-ai__end">
{{ item.truePrice }}
<view class="old-price">
{{ item.productInfo.otPrice }}
</view>
</view>
<!-- cart number -->
<view
class="cart-num flex flex-ai__center flex-jc__sb"
@click.stop=""
>
<view
class="button"
@click="handleCartNumberChange(item,'minus')"
>
<uv-icon
name="minus"
color="#333"
size="12"
></uv-icon>
</view>
<view class="input">
<input
type="number"
inputmode="numeric"
v-model="item.cartNum"
@blur="(e)=>handleCartNumberInputChange(e,item)"
>
</view>
<view
class="button"
@click="handleCartNumberChange(item,'plus')"
>
<uv-icon
name="plus"
color="#333"
size="12"
></uv-icon>
</view>
</view>
</view>
</view>
</template>
</Goods>
</view>
</view>
<!-- 选中了的结算统计信息 -->
<view :class="{'select-product-settle-info':true,show:shoppingSelect.length>0}">
<view
class="row flex flex-ai__center flex-jc__sb"
v-for="(item,index) in settleFields"
:key="index"
>
<view class="label">
{{ item.label }}
</view>
<view v-if="statisticsInfo">
{{ item.prefix }} {{ statisticsInfo[item.field].toFixed(2) }}
</view>
</view>
</view>
</card>
</uv-checkbox-group>
<!-- bottom action row -->
<view class="screen action-bar ">
<view class="action-info">
<view class="action-checkbox">
<uv-checkbox-group
shape="circle"
activeColor="#ee6d46"
>
<uv-checkbox
name="all"
:checked="shoppingSelectAll"
@change="handleSelectAll"
>
全选
</uv-checkbox>
</uv-checkbox-group>
</view>
</view>
<view class="action-btns">
<view
class="action-total"
v-show="!manage"
>
总计{{ statisticsInfo ? statisticsInfo.totalPrice.toFixed(2) : "0.00" }}
</view>
<view
class="button"
v-if="!manage"
@click="submitOrder"
>结算
</view>
<view
v-else
class="button"
@click="openDelModal(modalRef)"
>
删除
</view>
</view>
</view>
</view>
<!-- null data -->
<CartEmpty v-else />
<!-- 商品推荐 -->
<Recommend />
<view class="action-height"></view>
<view class="h5-tabbar-height"></view>
<!-- sku select -->
<GoodAttrSelect
style="z-index: 999"
:id="openSkuProductId"
ref="goodsAttrSelectRef"
@close="handleCloseSkuSelect"
@submit="(e)=>handleSubmitSkuSelect(e, goodsAttrSelectRef,cartList,handleCartNumberInputChange,doGetCartList)
"
/>
<!-- delete modal -->
<Modal
ref="modalRef"
content="确认要删除这些购物车数据吗?"
@confirm="doDelete"
/>
<ReturnTop :scroll-top="scrollTop" />
</template>
<script setup>
import { ref } from 'vue'
import Goods from "@/components/goodsComponents/Goods.vue";
import GoodAttrSelect from "@/components/good-attr-select/good-attr-select.vue";
import Modal from "@/components/Modal/index.vue"
import { settleFields } from "@/pages/shoppingCart/index.data";
import { useCartData, useCartNumber, useCartOption, useSku } from "@/pages/shoppingCart/index.utils";
import CartEmpty from "@/pages/shoppingCart/components/CartEmpty.vue";
import Header from "@/components/Header/index.vue"
import { onHide, onPageScroll, onReachBottom } from "@dcloudio/uni-app";
import Recommend from "@/components/Recommend/index.vue";
import { useScroll } from "@/hooks/useScroll";
import ReturnTop from "@/components/ReturnTop/index.vue"
const modalRef = ref() // 删除弹窗
const goodsAttrSelectRef = ref() // 更改sku
const {
showEmpty,
cartList,
doGetCartList
} = useCartData();
const {
manage,
manageStr,
shoppingSelect,
shoppingSelectAll,
handleSingleSelect,
handleSelectAll,
statisticsInfo,
computeSelectInfoByShoppingSelect,
openDelModal,
doDelete,
submitOrder,
} = useCartOption({cartList, doGetCartList})
const {
openSkuProductId,
handleOpenSkuSelect,
handleCloseSkuSelect,
handleSubmitSkuSelect
} = useSku()
const {
handleCartNumberInputChange,
handleCartNumberChange
} = useCartNumber({afterChange: computeSelectInfoByShoppingSelect})
onHide(() => {
modalRef.value?.close()
goodsAttrSelectRef.value?.close()
})
const {scrollTop} = useScroll()
</script>
<style lang="scss">
.cart-manage {
padding: 20rpx 34rpx;
font-size: 28rpx;
color: #333333;
background-color: #fff;
display: flex;
justify-content: flex-end;
border-bottom: 1rpx solid #f9f9f9;
}
// 商品SKU 数量等操作条
.goods-options {
width: 100%;
.sku-row {
margin-bottom: 30rpx;
.sku-info {
@include usePadding(10, 4);
border: 1rpx solid #ccc;
border-radius: 5rpx;
font-size: 24rpx;
transition: all .3s;
max-width: 100%;
.info {
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
&:active {
scale: 1.1;
}
.icon {
margin-left: 15rpx;
}
}
}
.price-row {
width: 100%;
.price-box {
font-size: 30rpx;
.old-price {
font-size: 20rpx;
color: $tips-color;
text-decoration: line-through;
margin-left: 10rpx;
}
}
.cart-num {
font-size: 24rpx;
.input {
width: 120rpx;
input {
width: 100%;
text-align: center;
color: #333;
}
}
.button {
font-size: 32rpx;
width: 34rpx;
aspect-ratio: 1/1;
border-radius: 5rpx;
border: 2rpx solid #cccccc;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
transition: all .3s;
&:active {
scale: 1.2;
}
}
}
}
}
// 统计信息
.select-product-settle-info {
@include usePadding(40, 0);
font-size: 28rpx;
transition: height .3s;
height: 0;
overflow: hidden;
.row {
margin: 20rpx 0;
}
&.show {
@include usePadding(40, 10);
border-top: 1rpx solid #E6E6E6;
height: 260rpx;
}
}
.action-bar {
z-index: 89;
height: 100rpx;
.action-btns {
height: 100%;
padding: 0 0;
.action-total {
padding-right: 30rpx;
font-size: 34rpx;
}
.button {
margin: 0 0;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 0 50rpx;
background: $primary-color;
color: $white-color;
}
}
}
// #ifndef H5
.action-height {
width: 100%;
height: 100rpx;
background: #fff;
}
// #endif
.shopping-checkbox {
width: 100%;
.shopping-item {
display: flex;
align-items: center;
padding: 0 20rpx;
box-sizing: border-box;
margin-bottom: 50rpx;
.good {
width: 93%;
position: relative;
}
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<layout class="bargaining">
<view class="swiper">
<image src="@/static/images/kjzq.png" />
<image src="https://b2c-pro-static-dev.zkthink.com/static/images/kjzq.png" />
</view>
<blank size="15"></blank>
<container min>

View File

@ -37,7 +37,7 @@
<Empty
v-else
padding="120rpx 0"
:icon-src="emptyIcon"
:icon-src="emptyCouponIcon"
>
暂无可用的优惠券
</Empty>
@ -56,8 +56,6 @@
<script setup>
import { ref, unref } from 'vue';
import emptyIcon from '@/static/icon/empty/优惠券.png'
import Empty from "@/components/Empty/index.vue"
import { useInterface } from "@/hooks/useInterface";
import { getCartCoupon } from "@/api/coupon";
@ -65,7 +63,7 @@ import CouponItem from "@/pages/discountCoupon/components/CouponItem.vue";
import Popup from '@/components/Popup/index.vue';
import UvRadio from "@/uni_modules/uv-radio/components/uv-radio/uv-radio.vue";
import UvRadioGroup from "@/uni_modules/uv-radio/components/uv-radio-group/uv-radio-group.vue";
import { emptyCouponIcon } from "@/utils/images";
const props = defineProps(["id", 'currentCouponId'])
const emit = defineEmits(['submitCoupon', 'close'])

View File

@ -5,8 +5,8 @@
* @descriptionindex.data
* @update: 2023-11-07 18:16
* */
import wechatIcon from '@/static/icon/pay/weixin.png'
import aliIcon from '@/static/icon/pay/zhifubao.png'
import { wechatIcon } from "@/utils/images";
import { aliIcon } from "@/utils/images";
import { PayType } from "@/utils/paymentUtils";
export const addressTabs = [

View File

@ -1,7 +1,7 @@
<script setup>
import UvNavbar from "@/uni_modules/uv-navbar/components/uv-navbar/uv-navbar.vue";
import { useRouter } from "@/hooks/useRouter";
import { onLoad, onPageScroll } from "@dcloudio/uni-app";
import { onLoad, onPageScroll, onShow } from "@dcloudio/uni-app";
import { ref, unref } from "vue";
import { useMainStore } from '@/store/store';
import { storeToRefs } from "pinia";
@ -159,7 +159,7 @@ async function doCreateServiceOrder() {
}
}
useScroll()
const {scrollTop} = useScroll()
/**
* 检查路由参数
@ -176,18 +176,20 @@ onLoad(async options => {
try {
const params = getParams(options)
await checkRouterParam(params)
await doGetSelectAddress()
await doGetInitConfirmOrder()
} catch (e) {
console.error(e)
}
})
onShow(async ()=>{
await doGetSelectAddress()
})
</script>
<template>
<view class="order-confirm">
<!-- header -->
<Header>
<Header :scroll-top="scrollTop">
提交订单
</Header>
<!-- 地址 -->
@ -235,7 +237,7 @@ onLoad(async options => {
</view>
<image
class="arrow-icon"
src="@/static/images/next.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/next.png"
alt=""
/>
</view>
@ -247,7 +249,7 @@ onLoad(async options => {
点击添加地址
<image
class="arrow-icon"
src="@/static/images/next.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/next.png"
alt=""
/>
</view>
@ -313,8 +315,9 @@ onLoad(async options => {
{{ row.prefix }}
{{ orderDetail["priceGroup"][row.field]?.toFixed(2) }}
<image
v-if="row.field=== 'couponPrice'"
class="arrow-icon"
src="@/static/images/next.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/next.png"
alt=""
/>
</view>

View File

@ -41,7 +41,7 @@
<view class="address-actions-edit">
<img
class="image"
src="@/static/images/next.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/next.png"
alt=""
>
</view>
@ -71,7 +71,7 @@
<view class="address-actions-edit">
<img
class="image"
src="@/static/images/next.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/next.png"
alt=""
>
</view>
@ -101,7 +101,7 @@
<view class="address-actions-edit">
<img
class="image"
src="@/static/images/next.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/next.png"
alt=""
>
</view>
@ -150,7 +150,7 @@
<view class="simple-cell">
<view class="icon simple-cell-icon">
<img
src="@/static/images/swiper.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/swiper.png"
alt=""
>
</view>
@ -171,7 +171,7 @@
<view class="simple-cell">
<view class="icon simple-cell-icon">
<img
src="@/static/images/swiper.png"
src="https://b2c-pro-static-dev.zkthink.com/static/images/swiper.png"
alt=""
>
</view>

View File

@ -130,18 +130,19 @@ function toLink(listItem) {
.dot {
z-index: 99;
position: absolute;
background: red;
background: #EE6D46;
color: #fff;
right: 20%;
top: 0;
transform: translateY(-20%);
font-size: 22rpx;
width: 35rpx;
height: 35rpx;
font-size: 18rpx;
width: 38rpx;
height: 38rpx;
text-align: center;
line-height: 35rpx;
line-height: 38rpx;
box-sizing: border-box;
border-radius: 50%;
border: 2rpx solid #ffffff;
}
.icon {

View File

@ -5,22 +5,8 @@
* @descriptionindex.data
* @update: 2023-11-09 15:21
* */
import toPayIcon from '@/static/images/icon-dfk.png'
import toFHIcon from '@/static/images/icon-dfh.png'
import toSHIcon from '@/static/images/icon-dsh.png'
import toPJIcon from '@/static/images/icon-dpj.png'
import toZJIcon from '@/static/images/icon-wdzj.png'
import toYHQIcon from '@/static/images/icon-yhq.png'
import toSCIcon from '@/static/images/icon-wdsc.png'
import toZBIcon from '@/static/images/icon-kqzb.png'
import toTGIcon from '@/static/images/icon-wdtg.png'
import toKJIcon from '@/static/images/icon-kqjl.png'
import toSHOIcon from '@/static/images/icon-kqjl.png'
import toKFIcon from '@/static/images/icon-lxkf.png'
import toDZIcon from '@/static/images/icon-address.png'
import toZHIcon from '@/static/images/icon-zhsz.png'
import { toPayIcon, toFHIcon, toSHIcon, toPJIcon, toZJIcon, toYHQIcon, toSCIcon, toZBIcon, toTGIcon, toKJIcon, toSHOIcon, toKFIcon, toDZIcon, toZHIcon } from "@/utils/images";
export const orderIconList = [
{

View File

@ -12,7 +12,7 @@
>
<image
class="head"
src="@/static/icon/user/mine.png"
src="https://b2c-pro-static-dev.zkthink.com/static/icon/user/mine.png"
/>
<view class="user-info">
点击登录

View File

@ -15,6 +15,7 @@ export function useRequest() {
async function doUpdateAvatar(file) {
try {
await upload({
url:'/member/user/update-avatar',
filePath: file.url,
name: 'avatarFile'
});

View File

@ -1,11 +1,6 @@
<template>
<layout>
<uv-navbar
:fixed="false"
title="账号设置"
left-arrow
@leftClick="goBack"
/>
<Header>账号设置</Header>
<view v-if="user">
<view class="y-list">
<uv-upload
@ -146,7 +141,7 @@ import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { storeToRefs } from 'pinia'
import { objectURLToBlob } from '@/utils'
import Header from "@/components/Header/index.vue"
import { useMainStore } from '@/store/store'
import { updateAvatar, updateNickname } from '@/api/user'
import { useGlobalProperties } from "@/hooks";

View File

@ -38,6 +38,9 @@ export const useMainStore = defineStore('main', {
this.address = []
this.moreLoading = true
},
clearSelectAddress(){
this.selectAddress = null
},
async getAddressList(page) {
let res = await getAddressList({page: page})
if (res.length) {

View File

@ -40,3 +40,9 @@ $black-color: #000;
width: 100%;
height: var(--window-bottom); // docs https://zh.uniapp.dcloud.io/matter.html#h5-%E5%BC%80%E5%8F%91%E6%B3%A8%E6%84%8F
}
.tabbar-height{
height: 118rpx;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}

View File

@ -669,7 +669,7 @@ image {
height: 25px !important;
line-height: 25px !important;
font-size: 12px !important;
bottom: 15rpx;
bottom: 30rpx;
border-radius: 0 !important;
}
}
@ -903,14 +903,14 @@ image {
display: flex;
align-items: center;
padding: 0 34rpx;
height: 100rpx;
height: 118rpx;
}
.action-icons {
flex: 1;
display: flex;
align-items: center;
height: 100rpx;
height: 118rpx;
padding-left: 20rpx;
&-item {
@ -957,7 +957,7 @@ image {
}
.uv-button {
height: 80rpx;
height: 70rpx;
border-radius: 0 !important;
}
}
@ -1201,3 +1201,11 @@ image {
}
}
}
.uni-tabbar{
height: 118rpx;
.uni-tabbar__label{
font-size: 20rpx;
line-height: 28rpx;
}
}

View File

@ -1,4 +1,5 @@
// 缓存key
export const CacheKey = {
PAY_INFO: 'pay_info', // 支付信息
TOP_TOUCH_KEY:'top_touch_key'
}

View File

@ -17,7 +17,7 @@ export const WechatProvider = 'wxpay'
// 支付类型(后端用)
export const ServiceFrom = {
'h5': 'weixin_h5', // H5微信内h5、微信外H5
'h5': 'h5', // H5微信内h5、微信外H5
'weixin': 'weixin_applet', // 微信小程序
'app': 'weixin_app' // 微信APP
}

View File

@ -15,6 +15,22 @@ export function formatDate(date, format) {
.replace(/ss/g, seconds);
}
export function formatRemainTime(time) {
let remainTimeStr=''
const seconds = Math.floor(time / 1000)
const days = Math.floor(seconds / (3600 * 24))
const hours = Math.floor((seconds % (3600 * 24)) / 3600)
// const minutes = Math.floor((seconds % 3600) / 60)
// const remainingSeconds = seconds % 60
if(days>0){
remainTimeStr += `${days}`
}
if(hours>0){
remainTimeStr += `${hours}小时`
}
return `还剩${remainTimeStr}自动确认`
}
/**
* 正则检测大陆手机号
* @param phone