This commit is contained in:
li tong bao
2022-06-23 16:59:10 +08:00
83 changed files with 3305 additions and 889 deletions
@@ -0,0 +1,202 @@
import { CancelOrderApi, ReceiveOrderApi } from "@/api/order"
import { alert } from "@/common/common"
import { ORDER_STATUS, SALE_MODE } from "@/common/enum"
import { ScrollView, Text, View } from "@tarojs/components"
import Taro from "@tarojs/taro"
import { useCallback, useRef, memo, useState, useEffect, useMemo } from "react"
import styles from './index.module.scss'
type Param = {
orderInfo: {
status: number, //订单状态
orderId: number, //订单id
actual_amount: number, //实付金额
wait_pay_amount: number, //待付金额
sale_mode: number //订单类型
}|null,
onClick?: (val: number) => void //点击后触发的事件,返回订单状态
}
export default memo(({orderInfo, onClick}:Param) => {
//订单状态枚举
const {
SaleOrderStatusBooking,
SaleOrderStatusArranging,
SaleOrderStatusArranged,
SaleOrderStatusWaitingDelivery,
SaleOrderStatusComplete,
SaleOrderStatusRefund,
SaleOrderStatusWaitingPayment,
SaleOrderStatusWaitingReceipt,
SaleOrderStatusAlreadyReceipt,
SaleorderstatusWaitingPrePayment
} = ORDER_STATUS
//订单类型
const {
SaLeModeBulk,
SaleModeLengthCut,
SaLeModeWeightCut,
} = SALE_MODE
//订单按钮按订单状态归类, value是该订单状态,可能该按钮会出现
const orderBtnsList = useRef([
{
id: 1,
value: [SaleOrderStatusBooking.value,
SaleOrderStatusArranging.value,
SaleOrderStatusArranged.value,
SaleOrderStatusWaitingPayment.value,
SaleOrderStatusWaitingDelivery.value], //取消订单按钮对应: 待接单,配布中,已配布, 待付款, 待发货
label: '取消订单'
},
{
id: 2,
value: [SaleorderstatusWaitingPrePayment.value, SaleOrderStatusWaitingPayment.value, SaleOrderStatusWaitingDelivery.value, SaleOrderStatusWaitingReceipt.value, SaleOrderStatusAlreadyReceipt.value, SaleOrderStatusComplete.value], //去付款按钮对应:待付款, 待发货, 待收货, 已收货, 已完成
label: '去付款'
},
{
id: 3,
value: [SaleOrderStatusWaitingDelivery.value], //申请退款按钮对应: 待发货
label: '申请退款'
},
{
id: 4,
value: [SaleOrderStatusWaitingReceipt.value, SaleOrderStatusAlreadyReceipt.value, SaleOrderStatusComplete.value, SaleOrderStatusRefund.value], //取消订单按钮对应: 待收货, 已收货, 已完成, 已退款
label: '查看物流'
},
{
id: 5,
value: [SaleOrderStatusWaitingReceipt.value, SaleOrderStatusAlreadyReceipt.value, SaleOrderStatusRefund.value], //申请退货按钮对应: 待收货, 已收货, 已退款
label: '申请退货'
},
{
id: 6,
value: [SaleOrderStatusWaitingReceipt.value], //确认收货按钮对应: 待收货
label: '确认收货'
},
{
id: 7,
value: [SaleOrderStatusWaitingReceipt.value,SaleOrderStatusAlreadyReceipt.value,SaleOrderStatusComplete.value,SaleOrderStatusRefund.value], //再次购买按钮对应: 待收货,已收货,已完成, 已退款
label: '再次购买'
},
{
id: 8,
value: [SaleOrderStatusBooking.value], //按钮对应: 待接单
label: '退款'
},
])
//判断是否显示该按钮
const orderBtnsShow = (item) => {
if(orderInfo) {
if(item.id == 1) {
//取消订单按钮
return( orderInfo.actual_amount == 0 && item.value.includes(orderInfo.status)) //在待发货之前没有付过款
} else if (item.id == 2) {
//去付款按钮
return( orderInfo.wait_pay_amount != 0 && item.value.includes(orderInfo.status)) //只要没有付完款就显示
} else if(item.id == 3 ) {
//申请退款, 只有大货才有
return (orderInfo.sale_mode == SaLeModeBulk.value && orderInfo.actual_amount != 0 && item.value.includes(orderInfo.status)) //大货在待发货付过款
} else if( item.id == 8) {
//退款按钮(直接退款不用申请), 只有散剪和剪板有
return (orderInfo.sale_mode != SaLeModeBulk.value && orderInfo.actual_amount != 0 && item.value.includes(orderInfo.status)) //散剪和剪板在待接单时付过款
}
else {
//其他按钮
return item.value.includes(orderInfo.status)
}
}
}
//显示的按钮数组
const orderBtnsShowList: {id: number, value: any, label: string}[] = useMemo(() => {
return orderBtnsList.current.filter(item => {
return orderBtnsShow(item)
})
}, [orderInfo])
//点击按钮操作
const submitBtns = (val, index) => {
(val == 1)&&cancelOrder(); //取消订单按钮
(val == 2)&&onClick?.(2); //去付款按钮
(val == 6)&&receiveOrder(); //确认收货
}
//取消订单
const {fetchData: cancelFetchData} = CancelOrderApi()
const cancelOrder = () => {
Taro.showModal({
title: '要取消该订单吗?',
success: async function (res) {
if (res.confirm) {
let res = await cancelFetchData({id: orderInfo?.orderId})
if(res.success) {
alert.success('取消成功')
onClick?.(1)
} else {
alert.none(res.msg)
}
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
//确认订单
const {fetchData: receiveOrderFetchData} = ReceiveOrderApi()
const receiveOrder = async () => {
console.log('123456')
Taro.showModal({
title: '确定收货?',
success: async function (res) {
if (res.confirm) {
let res = await receiveOrderFetchData({sale_order_id: orderInfo?.orderId})
if(res.success){
onClick?.(6)
alert.success('收货成功')
} else {
alert.error('收货失败')
}
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
//显示更多按钮
const [showMore, setShowMore] = useState(false)
const styleTop = useMemo(() => {
return {top:`-${(orderBtnsShowList.length - 3)*70 + 10}rpx`, left: `-${10}rpx`}
}, [orderBtnsShowList])
return (
<View className={styles.btns_list}>
{(orderBtnsShowList.length > 3)&&<View className={styles.more}>
<Text onClick={() => setShowMore(true)}>更多</Text>
{showMore&&<View className={styles.more_con}>
<View className={styles.more_list} style={styleTop}>
{orderBtnsShowList.map((item, index) => {
return ((index >= 3) &&<View className={styles.more_item} key={item.id} onClick={() => submitBtns(item.id, index)}>{item.label}</View>)
})}
</View>
<View className={styles.more_bg} catchMove onClick={() => setShowMore(false)}></View>
</View>}
</View>}
<View className={styles.list_scroll}>
{orderBtnsShowList.map((item, index) =>
(index < 3)&&<View key={item.id} className={styles.btns_item} onClick={() => submitBtns(item.id, index)}>{item.label}</View>
)}
</View>
</View>
)
})
@@ -0,0 +1,87 @@
.btns_list{
width: 100%;
// margin-top: 30px;
display: flex;
align-content: center;
.more{
font-size: 28px;
width: 143px;
display: flex;
align-items: center;
color: $color_font_two;
padding-left: 20px;
position: relative;
.more_list{
position: absolute;
background-color: #fff;
width: 226px;
box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.06);
border-radius: 10px;
padding: 0 20px;
box-sizing: border-box;
z-index:999;
&::before{
z-index: 1;
position: absolute;
bottom: -7px;
left: 50px;
width: 15px;
height: 15px;
content: " ";
transform: rotate(45deg);
background: #fff;
box-sizing: border-box;
box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.1);
}
.more_item{
font-size: 28px;
height: 70px;
line-height: 70px;
text-align: center;
&:nth-last-child(n+2) {
border-bottom: 1PX solid #F0F0F0;
}
}
}
.more_bg{
position:fixed;
width: 100vw;
height: 100vh;
top: 0;
left: 0;
}
}
.scroll{
white-space: nowrap;
width: 100%;
}
.list_scroll{
white-space: nowrap;
width: 100%;
text-align: right;
}
.btns_item{
padding: 0 15px;
width: 130px;
border: 2px solid #dddddd;
border-radius: 38px;
text-align: center;
line-height: 60px;
font-size: $font_size;
color: $color_font_three;
display:inline-block;
&:nth-child(n+2) {
margin-left: 32px;
}
&:nth-last-child(1) {
border: 2px solid $color_main;
color: $color_main;
}
}
.end_btn{
border: 2px solid $color_main;
color: $color_main;
}
}
+193
View File
@@ -0,0 +1,193 @@
import { CancelOrderApi, ReceiveOrderApi } from "@/api/order"
import { alert } from "@/common/common"
import { AFTER_ORDER_STATUS, ORDER_STATUS, SALE_MODE } from "@/common/enum"
import {Text, View } from "@tarojs/components"
import Taro from "@tarojs/taro"
import {useRef, memo, useState, useMemo } from "react"
import classnames from "classnames";
import styles from './index.module.scss'
import { ReturnApplyOrderCancelApi } from "@/api/salesAfterOrder"
type Param = {
orderInfo: {
stage: number, //售后状态
orderId: number, //订单id
sale_mode: number //订单类型
type: number //1退货,2退款
},
onClick?: (val: number) => void //点击后触发的事件,返回订单状态
}
export default memo(({orderInfo, onClick}:Param) => {
//售后订单状态
const {
ReturnStageApplying,
ReturnStageWaitCheck,
ReturnStageChecked,
ReturnStageReturned,
ReturnStageCancel,
ReturnStageQualityCheckPendingRefund,
ReturnStageServiceOrderPendingRefund,
ReturnStageRejected
} = AFTER_ORDER_STATUS
//订单类型
const {
SaLeModeBulk,
SaleModeLengthCut,
SaLeModeWeightCut,
} = SALE_MODE
//售后按钮按售后状态归类, value是该订单状态,可能该按钮会出现
const orderBtnsList = useRef([
{
id: 1,
value: [ReturnStageApplying.value, ReturnStageWaitCheck.value],
label: '取消退货'
},
{
id: 2,
value: [ReturnStageWaitCheck.value],
label: '退货物流'
},
{
id: 3,
value: [ReturnStageChecked.value, ReturnStageQualityCheckPendingRefund.value],
label: '查看物流'
},
{
id: 4,
value: [ReturnStageQualityCheckPendingRefund.value, ReturnStageServiceOrderPendingRefund.value, ReturnStageReturned.value],
label: '质检结果'
},
{
id: 5,
value: [ReturnStageServiceOrderPendingRefund.value, ReturnStageReturned.value],
label: '退货码单'
},
{
id: 6,
value: [ReturnStageApplying.value, ReturnStageServiceOrderPendingRefund.value],
label: '取消退款'
},
{
id: 7,
value: [ReturnStageServiceOrderPendingRefund.value, ReturnStageReturned.value],
label: '退款码单'
},
{
id: 8,
value: [],
label: '申请记录'
},
])
//判断是否显示该按钮
const orderBtnsShow = (item) => {
if(!orderInfo) return false
if(item.id == 1) {
//取消退货
return (orderInfo.type == 1)&&item.value.includes(orderInfo.stage)
} else if (item.id == 6) {
//取消退款
return (orderInfo.type == 2)&&item.value.includes(orderInfo.stage)
} else {
return item.value.includes(orderInfo.stage)
}
}
//显示的按钮数组
const orderBtnsShowList: {id: number, value: any, label: string}[] = useMemo(() => {
return orderBtnsList.current.filter(item => {
return orderBtnsShow(item)
})
}, [orderInfo])
//点击按钮操作
const submitBtns = (val, index) => {
if (val == 1) {
cancelOrder()
} else if (val == 6) {
receiveOrder()
} else {
onClick?.(val)
}
}
//取消退货
const {fetchData: returnApplyOrderCancelFetchData} = ReturnApplyOrderCancelApi()
const cancelOrder = () => {
Taro.showModal({
title: '要取消退货吗?',
success: async function (res) {
if (res.confirm) {
let res = await returnApplyOrderCancelFetchData({id: orderInfo?.orderId})
if(res.success) {
alert.success('取消成功')
onClick?.(1)
} else {
alert.none(res.msg)
}
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
//确认订单
const {fetchData: receiveOrderFetchData} = ReceiveOrderApi()
const receiveOrder = async () => {
console.log('123456')
Taro.showModal({
title: '确定收货?',
success: async function (res) {
if (res.confirm) {
let res = await receiveOrderFetchData({sale_order_id: orderInfo?.orderId})
if(res.success){
onClick?.(6)
alert.success('收货成功')
} else {
alert.error('收货失败')
}
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
//显示更多按钮
const [showMore, setShowMore] = useState(false)
const styleTop = useMemo(() => {
return {top:`-${(orderBtnsShowList.length - 3)*70 + 10}rpx`, left: `-${10}rpx`}
}, [orderBtnsShowList])
return (
<View className={styles.btns_list}>
{(orderBtnsShowList.length > 3)&&<View className={styles.more}>
<Text onClick={() => setShowMore(true)}>更多</Text>
{showMore&&<View className={styles.more_con}>
<View className={styles.more_list} style={styleTop}>
{orderBtnsShowList.map((item, index) => {
return ((index >= 3) &&<View className={styles.more_item} key={item.id} onClick={() => submitBtns(item.id, index)}>{item.label}</View>)
})}
</View>
<View className={styles.more_bg} catchMove onClick={() => setShowMore(false)}></View>
</View>}
</View>}
<View className={styles.list_scroll}>
{orderBtnsShowList.map((item, index) =>
(index < 3)&&<View key={item.id} className={classnames(styles.btns_item)} onClick={() => submitBtns(item.id, index)}>{item.label}</View>
)}
</View>
</View>
)
})
+17 -8
View File
@@ -4,19 +4,25 @@
align-items: center;
justify-content: space-between;
width: 100%;
.reduce, .plus{
font-size: $font_size_big;
.plus{
color: $color_main;
width: 46px;
height: 46px;
display: flex;
align-items: center;
justify-content:center;
text-align: center;
line-height: 43px;
font-size: 50px;
background-color: $color_main;
color: #fff;
border-radius: 8px;
}
.reduce {
font-size: 50px;
width: 46px;
height: 46px;
text-align: center;
line-height: 43px;
color:#007AFF;
}
.input{
display: flex;
align-items: flex-end;
@@ -25,10 +31,13 @@
box-sizing: border-box;
width: 106px;
border-radius: 10px;
input{
font-size: $font_size_medium;
text-align: right;
padding-right: 10px;
}
}
input{
font-size: $font_size_medium;
}
.unit{
font-size: $font_size_min;
color: $color_font_two;
+7 -3
View File
@@ -11,12 +11,14 @@ type params = {
onChange?:(val:number) => void,
onBlue?:(val:number) => void, //失去焦点触发
onClickBtn?:(val:number) => void,
unit?: string
unit?: string,
disable?: true|false, //是否禁用
}
export default ({minNum = 0, maxNum = 100, step=1, digits = 0, defaultNum = 0, onChange, onBlue, onClickBtn, unit = ''}: params) => {
export default ({minNum = 0, maxNum = 10000, step=1, digits = 0, defaultNum = 0, onChange, onBlue, onClickBtn, unit = '', disable = false}: params) => {
const [value, setValue] = useState<any>({count:defaultNum})
const onPlus = () => {
if(disable) return false
let {count} = value
let num_res = Big(count).add(step).toNumber()
num_res = num_res >= maxNum?maxNum:num_res
@@ -26,9 +28,10 @@ export default ({minNum = 0, maxNum = 100, step=1, digits = 0, defaultNum = 0, o
onClickBtn?.(parseFloat(num_res))
}
const minus = () => {
if(disable) return false
let {count} = value
let num_res = Big(count).minus(step).toNumber()
num_res = num_res < minNum?0:num_res
num_res = num_res < minNum?minNum:num_res
setValue({...value, count:num_res})
onChange?.(parseFloat(num_res))
onClickBtn?.(parseFloat(num_res))
@@ -102,6 +105,7 @@ export default ({minNum = 0, maxNum = 100, step=1, digits = 0, defaultNum = 0, o
onInput={onInputEven}
onBlur={onBluerEven}
type='digit'
disabled={disable}
/>
<View className={styles.unit}>{unit}</View>
</View>
+37
View File
@@ -0,0 +1,37 @@
.main{
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
.reduce, .plus{
font-size: $font_size_big;
color: $color_main;
width: 46px;
height: 46px;
display: flex;
align-items: center;
justify-content:center;
font-size: 50px;
background-color: $color_main;
color: #fff;
border-radius: 8px;
}
.input{
display: flex;
align-items: flex-end;
background-color: #fff;
padding: 5px 10px;
box-sizing: border-box;
width: 106px;
border-radius: 10px;
}
input{
font-size: $font_size_medium;
}
.unit{
font-size: $font_size_min;
color: $color_font_two;
}
}
+111
View File
@@ -0,0 +1,111 @@
import { Input, View } from "@tarojs/components"
import { useEffect, useMemo, useRef, useState } from "react"
import Big from 'big.js'
import styles from "./index.module.scss"
type params = {
minNum?: number, //最小值
maxNum?: number, //最大值
step?: number, //步长
defaultNum?: number, //默认值
digits?: number //多少位小数
onChange?:(val:number) => void,
onBlue?:(val:number) => void, //失去焦点触发
onClickBtn?:(val:number) => void,
unit?: string
}
export default ({minNum = 0, maxNum = 100, step=1, digits = 0, defaultNum = 0, onChange, onBlue, onClickBtn, unit = ''}: params) => {
const [value, setValue] = useState<any>({count:defaultNum})
const onPlus = () => {
let {count} = value
let num_res = Big(count).add(step).toNumber()
num_res = num_res >= maxNum?maxNum:num_res
num_res = formatDigits(num_res)
setValue({...value, count:num_res})
onChange?.(parseFloat(num_res))
onClickBtn?.(parseFloat(num_res))
}
const minus = () => {
let {count} = value
let num_res = Big(count).minus(step).toNumber()
num_res = num_res < minNum?0:num_res
setValue({...value, count:num_res})
onChange?.(parseFloat(num_res))
onClickBtn?.(parseFloat(num_res))
}
//保留小数
const formatDigits = (num) => {
num = num + ''
if(num.includes('.')&&digits > 0) {
console.log('num::',num.includes('.'))
let res = num.split('.')
let last_num = res[1].substr(0, digits)
return res[0] + '.' + last_num
}
return parseFloat(num)
}
//检查数据
const checkData = (val) => {
let num = parseFloat(val)
if(num > maxNum) return maxNum
if(num < minNum) return minNum
return val
}
const onInputEven = (e) => {
let res = e.detail.value
if(res === '') {
setValue({...value, count:minNum})
onChange?.(minNum)
}
else if(!isNaN(Number(res))) {
let count = formatDigits(res)
count = checkData(count)
setValue({...value, count})
onChange?.(parseFloat(count as string))
} else {
let num = parseFloat(res)
if(!isNaN(num)) {
let count = formatDigits(num)
count = checkData(count)
setValue({...value, count})
onChange?.(count as number)
} else {
setValue({...value, count:defaultNum})
onChange?.(defaultNum)
}
}
}
const onBluerEven = () => {
let num = parseFloat(value.count)
if(!isNaN(num)) {
let count = formatDigits(num)
count = checkData(count)
setValue({...value, count})
onBlue?.(count as number)
} else {
setValue({...value, count:defaultNum})
onBlue?.(defaultNum)
}
}
return (
<View className={styles.main}>
<View className={styles.reduce} onClick={() => minus()}>-</View>
<View className={styles.input}>
<Input
value={String(value.count)}
onInput={onInputEven}
onBlur={onBluerEven}
type='digit'
/>
<View className={styles.unit}>{unit}</View>
</View>
<View className={styles.plus} onClick={() => onPlus()}>+</View>
</View>
)
}
@@ -74,6 +74,11 @@
&:nth-child(n+2) {
margin-left: 32px;
}
&:nth-last-child(1) {
border: 2px solid $color_main;
color: $color_main;
}
}
.end_btn{
border: 2px solid $color_main;
+25 -15
View File
@@ -1,10 +1,12 @@
import { CancelOrderApi, ReceiveOrderApi } from "@/api/order"
import { alert } from "@/common/common"
import { alert, goLink } from "@/common/common"
import { ORDER_STATUS, SALE_MODE } from "@/common/enum"
import { ScrollView, Text, View } from "@tarojs/components"
import {Text, View } from "@tarojs/components"
import Taro from "@tarojs/taro"
import { useCallback, useRef, memo, useState, useEffect, useMemo } from "react"
import {useRef, memo, useState, useMemo } from "react"
import classnames from "classnames";
import styles from './index.module.scss'
import { AddShoppingCartApi } from "@/api/shopCart"
type Param = {
orderInfo: {
@@ -29,7 +31,8 @@ export default memo(({orderInfo, onClick}:Param) => {
SaleOrderStatusWaitingPayment,
SaleOrderStatusWaitingReceipt,
SaleOrderStatusAlreadyReceipt,
SaleorderstatusWaitingPrePayment
SaleorderstatusWaitingPrePayment,
SaleOrderStatusTaking
} = ORDER_STATUS
//订单类型
@@ -41,6 +44,7 @@ export default memo(({orderInfo, onClick}:Param) => {
//订单按钮按订单状态归类, value是该订单状态,可能该按钮会出现
const orderBtnsList = useRef([
{
id: 1,
value: [SaleOrderStatusBooking.value,
@@ -50,14 +54,9 @@ export default memo(({orderInfo, onClick}:Param) => {
SaleOrderStatusWaitingDelivery.value], //取消订单按钮对应: 待接单,配布中,已配布, 待付款, 待发货
label: '取消订单'
},
{
id: 2,
value: [SaleorderstatusWaitingPrePayment.value, SaleOrderStatusWaitingPayment.value, SaleOrderStatusWaitingDelivery.value, SaleOrderStatusWaitingReceipt.value, SaleOrderStatusAlreadyReceipt.value, SaleOrderStatusComplete.value], //去付款按钮对应:待付款, 待发货, 待收货, 已收货, 已完成
label: '去付款'
},
{
id: 3,
value: [SaleOrderStatusWaitingDelivery.value], //申请退款按钮对应: 待发货
value: [SaleOrderStatusWaitingDelivery.value, SaleOrderStatusTaking.value], //申请退款按钮对应: 待发货, 提货中
label: '申请退款'
},
// {
@@ -85,6 +84,11 @@ export default memo(({orderInfo, onClick}:Param) => {
value: [SaleOrderStatusBooking.value], //按钮对应: 待接单
label: '退款'
},
{
id: 2,
value: [SaleOrderStatusTaking.value, SaleorderstatusWaitingPrePayment.value, SaleOrderStatusWaitingPayment.value, SaleOrderStatusWaitingDelivery.value, SaleOrderStatusWaitingReceipt.value, SaleOrderStatusAlreadyReceipt.value, SaleOrderStatusComplete.value], //去付款按钮对应:待付款, 待发货, 待收货, 已收货, 已完成
label: '去付款'
},
])
@@ -123,10 +127,15 @@ export default memo(({orderInfo, onClick}:Param) => {
//点击按钮操作
const submitBtns = (val, index) => {
(val == 1)&&cancelOrder(); //取消订单按钮
(val == 2)&&onClick?.(2); //去付款按钮
(val == 6)&&receiveOrder(); //确认收货
if (val == 1) {
cancelOrder()
} else if (val == 6) {
receiveOrder()
} else if(val == 5) {
goLink('/pages/applyAfterSales/index',{id:orderInfo?.orderId})
} else {
onClick?.(val)
}
}
//取消订单
@@ -172,6 +181,7 @@ export default memo(({orderInfo, onClick}:Param) => {
})
}
//显示更多按钮
const [showMore, setShowMore] = useState(false)
const styleTop = useMemo(() => {
@@ -194,7 +204,7 @@ export default memo(({orderInfo, onClick}:Param) => {
<View className={styles.list_scroll}>
{orderBtnsShowList.map((item, index) =>
(index < 3)&&<View key={item.id} className={styles.btns_item} onClick={() => submitBtns(item.id, index)}>{item.label}</View>
(index < 3)&&<View key={item.id} className={classnames(styles.btns_item)} onClick={() => submitBtns(item.id, index)}>{item.label}</View>
)}
</View>
+6 -2
View File
@@ -25,7 +25,7 @@
border-radius: 10px;
}
.num{
padding: 5px 10px;
padding: 5px 10px 5px 20px;
font-size: $font_size_min;
position: absolute;
right:0;
@@ -51,7 +51,7 @@
.tag_list{
display: flex;
margin-top: 16px;
.tag{
.tag, .tag_g{
padding: 3px 10px;
background-color: #CDE5FF;
font-size: $font_size_min;
@@ -61,6 +61,10 @@
margin-left: 10px;
}
}
.tag_g{
background-color: #FFE6CE;
color: #EE7500;
}
}
.introduce{
font-size: $font_size_medium;
+1 -1
View File
@@ -22,7 +22,7 @@ export default ({desStatus = true, productList = []}:Params) => {
<View className={styles.title}><text>{formatHashTag(item.code, '')} </text>{item.name}</View>
<View className={styles.tag_list}>
<View className={styles.tag}>{item.width}</View>
<View className={styles.tag}>{item.weight_density}</View>
<View className={styles.tag_g}>{item.weight_density}</View>
</View>
<View className={styles.introduce}>{item.component}</View>
{desStatus&&<View className={styles.des}>{item.describe}</View>}
+15
View File
@@ -17,6 +17,11 @@
margin-right: 10px;
}
}
.count_all{
font-size: 22px;
color: #ABABAB;
padding: 30px 20px;
}
.search{
display: flex;
justify-content: space-between;
@@ -104,6 +109,15 @@
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
.btn_count{
width: 235px;
height: 64px;
background-color: #ECF5FF;
border-radius: 40px 0px 16px 0px;
padding: 0 20px;
display: flex;
align-items: center;
}
.price{
font-size: $font_size;
font-weight: 700;
@@ -150,6 +164,7 @@
justify-content: center;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
z-index: 999;
.buy_con{
width: 702px;
height: 95px;
+63 -17
View File
@@ -8,10 +8,11 @@ import styles from "./index.module.scss"
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import Taro from "@tarojs/taro";
import { alert, goLink } from "@/common/common";
import {GetShoppingCartApi, DelShoppingCartApi} from "@/api/shopCart"
import {GetShoppingCartApi, DelShoppingCartApi, UpdateShoppingCartApi} from "@/api/shopCart"
import { formatHashTag, formatImgUrl, formatPriceDiv } from "@/common/fotmat";
import { setParam } from "@/common/system";
import { debounce } from "@/common/util";
import Counter from "../counter";
type param = {
show?: true|false,
@@ -19,11 +20,9 @@ type param = {
}
export default ({show = false, onClose}: param) => {
const selectList = [
// {value:-1, title:'不限', unit:'', eunit:''},
{value:0, title:'大货', unit:'件', eunit:'kg'},
{value:1,title:'剪板', unit:'米', eunit:'m'},
{value:2,title:'散剪', unit:'米', eunit:'kg'},
{value:0, title:'大货', unit:'条', eunit:'kg', step:1, digits:0, minNum:1, maxNum:100000, defaultNum:1},
{value:1,title:'剪板', unit:'米', eunit:'m', step:1, digits:2, minNum:0.5, maxNum:9.99, defaultNum:1},
{value:2,title:'散剪', unit:'米', eunit:'kg', step:1, digits:2, minNum:5, maxNum:100000, defaultNum:10},
]
const [selectIndex, setSelectIndex] = useState(0)
@@ -53,7 +52,6 @@ export default ({show = false, onClose}: param) => {
const [loading, setLoading] = useState(false)
const {fetchData} = GetShoppingCartApi()
const getShoppingCart = async () => {
setLoading(true)
const {data} = await fetchData()
let color_list = data.color_list||[]
initList(color_list)
@@ -65,6 +63,7 @@ export default ({show = false, onClose}: param) => {
const initList = (color_list) => {
color_list?.map(item => {
if(selectIndex == item.sale_mode) item.select = true
item.count = formatCount(item)
})
}
@@ -74,6 +73,7 @@ export default ({show = false, onClose}: param) => {
setList([])
setSelectIndex(0)
} else {
setLoading(true)
getShoppingCart()
}
}, [show])
@@ -136,11 +136,13 @@ export default ({show = false, onClose}: param) => {
//删除购物车内容
const {fetchData:delShopFetchData} = DelShoppingCartApi()
const delSelect = () => {
getSelectId()
if(selectIds.current.length <= 0) return alert.none('请选择要删除的面料!')
Taro.showModal({
content: '删除所选商品?',
success: async function (res) {
if (res.confirm) {
getSelectId()
const res = await delShopFetchData({id:selectIds.current})
if(res.success) {
getShoppingCart()
@@ -180,17 +182,33 @@ export default ({show = false, onClose}: param) => {
//格式化数量
const formatCount = useCallback((item) => {
return item.sale_mode == 0? item.roll + '件': (item.length/100) + 'm'
console.log('item:::',item)
return item.sale_mode == 0? item.roll : (item.length/100)
}, [])
//预估金额
//格式化单位
const formatUnit = useCallback((item) => {
return item.sale_mode == 0? '条':'米'
}, [])
//预估金额和总条数
const estimatePrice = useMemo(() => {
let count = 0
let estimate_amount = 0
let product_list = new Set() //面料
let color_count = 0 //颜色数量
let all_count = 0 //总数量
list.map(item => {
if(item.select) count += item.estimate_amount
if(item.select) {
estimate_amount += item.estimate_amount
product_list.add(item.product_id)
color_count++
all_count += item.sale_mode == 0?item.roll: (item.length)
}
})
return Number(formatPriceDiv(count))
let all_count_text = selectIndex == 0?all_count + '条': (all_count/100) + '米'
return {price: Number(formatPriceDiv(estimate_amount)).toFixed(2), countText: `已选${product_list.size}种面料,${color_count}个颜色,共${all_count_text}`, color_count}
},[list])
//去结算
const orderDetail = debounce(() => {
@@ -199,11 +217,25 @@ export default ({show = false, onClose}: param) => {
alert.error('请选择面料')
} else {
let ids = selectIds.current.join('-')
setParam({ids, sale_mode:selectIndex})
setParam({ids, sale_mode:selectIndex}) //临时存储
closePopup()
goLink('/pages/order/comfirm')
}
}, 500)
//计数组件-当后端修改完成才修改前端显示
const {fetchData: fetchDataUpdateShoppingCart} = UpdateShoppingCartApi()
const [UpdateShoppingCartLoading, setUpdateShoppingCartLoading] = useState(false)
const getInputValue = debounce(async (num, item) => {
let roll = item.sale_mode == 0?parseFloat(num):0
let length = item.sale_mode != 0?(parseFloat(num)*100):0
setUpdateShoppingCartLoading(() => true)
let res = await fetchDataUpdateShoppingCart({id: item.id, roll, length})
setUpdateShoppingCartLoading(() => false)
if(res.success) {
getShoppingCart()
}
}, 300)
return (
<View className={styles.shop_cart_main}>
@@ -216,6 +248,7 @@ export default ({show = false, onClose}: param) => {
删除所选
</View>
</View>
<View className={styles.count_all}>{estimatePrice.countText}</View>
<View className={styles.search}>
{selectList.map((item) => {
return <View key={item.value} onClick={() => selectProduct(item.value)} className={classnames(styles.search_item, (selectIndex==item.value)&&styles.search_item_select)}>{item.title}</View>
@@ -240,7 +273,20 @@ export default ({show = false, onClose}: param) => {
</View>
<View className={styles.count}>
<View className={styles.price}><text>¥</text>{formatPirce(item.sale_price)}<text>/{selectList[selectIndex].eunit}</text></View>
<View className={styles.long}>×{formatCount(item)}</View>
{/* <View className={styles.long}>×{formatCount(item)}{selectList[selectIndex].unit}</View> */}
<View className={styles.btn_count}>
<Counter
onBlue={(e) => getInputValue(e, item)}
defaultNum={item.count}
step={selectList[selectIndex].step}
digits={selectList[selectIndex].digits}
onClickBtn={(e) => getInputValue(e, item)}
unit={formatUnit(item)}
minNum={selectList[selectIndex].minNum}
maxNum={selectList[selectIndex].maxNum}
disable={UpdateShoppingCartLoading}
/>
</View>
</View>
</View>
})}
@@ -258,11 +304,11 @@ export default ({show = false, onClose}: param) => {
<View className={classnames('iconfont', 'icon-gouwuche', styles.miconfont)}></View>
</View>
<View className={styles.price_con}>
<View className={styles.price_real}><text>¥</text>{estimatePrice}</View>
<View className={styles.price_real}><text>¥</text>{estimatePrice.price}</View>
<View className={styles.price_forecast}>预估金额</View>
</View>
<View className={styles.goPay} onClick={() => orderDetail()}>
去结算
去结算({estimatePrice.color_count})
</View>
</View>
</View>
+3 -2
View File
@@ -29,8 +29,9 @@
}
.sideBar_select_title_select{
background-color: $color_bg_one;
color: $color_font_one;
background-color: #007AFF;
color: #fff;
border-radius: 0px 14px 14px 0px;
}
}
.sideBar_con{
-1
View File
@@ -104,7 +104,6 @@ export default memo(({list = [],
)
})
}
<View className="common_safe_area_y"></View>
</ScrollView>
<View className={styles.sideBar_con}>
<InfiniteScroll statusMore={statusMore} hasMore={hasMore} selfonScrollToLower={() => selfOnScrolltolower?.()} refresherTriggered={refresherTriggered} refresherEnabled={true} selfOnRefresherRefresh={() => selfOnRefresherRefresh?.()}>
@@ -0,0 +1,36 @@
.other_desc{
// padding: 0 20px;
box-sizing: border-box;
.title{
font-size: $font_size;
font-weight: 700;
}
.textarea{
position: relative;
height: 165.4px;
.descDataNum{
position: absolute;
right: 10px;
bottom: 10px;
font-size: 22px;
color: #ABABAB;
}
}
.textarea_con, .textarea_con_pretend{
background-color: #f3f3f3;
border: 2px solid #e6e6e6;
border-radius: 10px;
width: 100%;
font-size: 25px;
height: 165.4px;
padding: 20px 20px 30px 20px;
box-sizing: border-box;
margin-top: 20px;
}
.textarea_con_pretend{
color: $color_font_two;
}
.textarea_con_pretend_ed{
color: #000;
}
}
+43
View File
@@ -0,0 +1,43 @@
import {Textarea, View } from "@tarojs/components";
import { memo, useMemo, useState } from "react";
import styles from './index.module.scss'
import classnames from "classnames";
//其他说明
type Param = {
title?: string,
onChange?: (val: string) => void,
placeholder?: string
}
export default memo(({onChange, title = '', placeholder = '请输入'}:Param) => {
const [descData, setDescData] = useState({
number: 0,
value: '',
count: 200,
show: false
})
const getDesc = (e) => {
let value = e.detail.value
let res = value
if(value.length > descData.count) {
res = value.slice(0, descData.count)
}
setDescData({...descData, number:res.length, value: res})
onChange?.(res)
}
const toggleShowRealTextarea = (show) => {
setDescData({...descData, show:show})
}
return (
<View className={styles.other_desc}>
<View className={styles.title}>{title}</View>
<View className={styles.textarea}>
{descData.show&&<Textarea autoFocus value={descData.value} onBlur={() => toggleShowRealTextarea(false)} className={styles.textarea_con} cursorSpacing={100} maxlength={descData.count} onInput={(e) => getDesc(e)}></Textarea>||
<View className={classnames(styles.textarea_con_pretend, descData.value&&styles.textarea_con_pretend_ed)} onClick={() => toggleShowRealTextarea(true)}>{descData.value||placeholder}</View>
}
<View className={styles.descDataNum}>{descData.number +'/'+ descData.count}</View>
</View>
</View>
)
})
@@ -0,0 +1,55 @@
.image_main{
display: flex;
align-items: center;
flex-wrap: wrap;
.uploadImg{
width: 202px;
height: 150px;
background: #f0f0f0;
border: 2px dashed #cccccc;
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
margin: 0 0 20px 20px;
position: relative;
.miconfont{
font-size: 50px;
}
.uploadText{
font-size: 26px;
color: $color_font_three;
}
}
.ImgItem{
width: 202px;
height: 150px;
background: #f0f0f0;
margin-left: 20px;
margin-bottom: 20px;
position: relative;
border-radius: 10px;
image{
width: 100%;
height: 100%;
border-radius: 10px;
}
.miconfont_close{
width: 43px;
height: 43px;
background-color: #ccc;
border-radius: 50%;
position: absolute;
right: -10px;
top: -10px;
text-align: center;
line-height: 43px;
color: #fff;
font-size: 30px;
}
}
}
+59
View File
@@ -0,0 +1,59 @@
import Taro, { FC } from "@tarojs/taro"
import { memo, useEffect, useState } from "react"
import useUploadCDNImg from "@/use/useUploadImage";
import { Image, Text, View } from "@tarojs/components";
import { formatImgUrl } from "@/common/fotmat";
import classnames from "classnames";
import styles from './index.module.scss'
//图片列表
type ImageParam = {
onChange?:(val: string[]) => void
}
const PictureItem:FC<ImageParam> = memo(({onChange}) => {
const {getWxPhoto} = useUploadCDNImg()
const [imageList, setImageLise] = useState<string[]>([])
//上传图片
const uploadImage = async () => {
let res:any = await getWxPhoto('after-sale')
if(res.code == 200) {
setImageLise([...imageList, res.url])
}
}
//删除图片
const delImage = (index) => {
imageList.splice(index,1)
setImageLise(() => [...imageList])
}
//监听上传的图片变化
useEffect(() => {
onChange?.(imageList||[])
}, [imageList])
//预览图片
const showImage = () => {
let list = imageList.map(item => {
return formatImgUrl(item)
})
Taro.previewImage({
current: list[0], // 当前显示
urls: list // 需要预览的图片http链接列表
})
}
return (
<View className={styles.image_main}>
{imageList.map((item, index) =>
<View className={styles.ImgItem}>
<Image mode="aspectFill" src={formatImgUrl(item)} onClick={showImage}></Image>
<View onClick={() => delImage(index)} className={classnames(styles.miconfont_close, 'iconfont icon-qingkong')}></View>
</View>)}
<View className={styles.uploadImg } onClick={uploadImage}>
<Text className={classnames(styles.miconfont, 'iconfont icon-saomazhifu')}></Text>
<Text className={styles.uploadText}>上传照片</Text>
</View>
</View>
)
})
export default PictureItem