对接售后退款申请

This commit is contained in:
czm 2022-06-24 19:54:01 +08:00
parent 9503d35dbb
commit 3d349d405a
14 changed files with 134 additions and 66 deletions

View File

@ -79,4 +79,14 @@ export const GetSaleOrderListApi = () => {
url: `/v1/mall/enum/returnExplain`, url: `/v1/mall/enum/returnExplain`,
method: "get", method: "get",
}) })
} }
/**
* 退
*/
export const ApplyRefundApi = () => {
return useRequest({
url: `/v1/mall/returnApplyOrder`,
method: "post",
})
}

View File

@ -15,28 +15,26 @@ type Param = {
sale_mode: number //订单类型 sale_mode: number //订单类型
type: number //1退货2退款 type: number //1退货2退款
}, },
onClick?: (val: number) => void //点击后触发的事件,返回订单状态 onClick?: (val: number) => void, //点击后触发的事件,返回订单状态
onBtnNull?: () => void //所有按钮都为空
} }
export default memo(({orderInfo, onClick}:Param) => { export default memo(({orderInfo, onClick, onBtnNull}:Param) => {
//售后订单状态 //售后订单状态
const { const {
ReturnStageApplying, ReturnStageApplying,
ReturnStageWaitCheck, ReturnStageWaitCheck,
ReturnStageChecked,
ReturnStageReturned, ReturnStageReturned,
ReturnStageCancel,
ReturnStageQualityCheckPendingRefund, ReturnStageQualityCheckPendingRefund,
ReturnStageServiceOrderPendingRefund, ReturnStageServiceOrderPendingRefund,
ReturnStageRejected
} = AFTER_ORDER_STATUS } = AFTER_ORDER_STATUS
//订单类型 //订单类型
const { // const {
SaLeModeBulk, // SaLeModeBulk,
SaleModeLengthCut, // SaleModeLengthCut,
SaLeModeWeightCut, // SaLeModeWeightCut,
} = SALE_MODE // } = SALE_MODE
//售后按钮按售后状态归类, value是该订单状态可能该按钮会出现 //售后按钮按售后状态归类, value是该订单状态可能该按钮会出现
const orderBtnsList = useRef([ const orderBtnsList = useRef([
@ -50,11 +48,11 @@ export default memo(({orderInfo, onClick}:Param) => {
value: [ReturnStageWaitCheck.value], value: [ReturnStageWaitCheck.value],
label: '退货物流' label: '退货物流'
}, },
{ // {
id: 3, // id: 3,
value: [ReturnStageChecked.value, ReturnStageQualityCheckPendingRefund.value], // value: [ReturnStageChecked.value, ReturnStageQualityCheckPendingRefund.value],
label: '查看物流' // label: '查看物流'
}, // },
{ {
id: 4, id: 4,
value: [ReturnStageQualityCheckPendingRefund.value, ReturnStageServiceOrderPendingRefund.value, ReturnStageReturned.value], value: [ReturnStageQualityCheckPendingRefund.value, ReturnStageServiceOrderPendingRefund.value, ReturnStageReturned.value],
@ -86,7 +84,6 @@ export default memo(({orderInfo, onClick}:Param) => {
//判断是否显示该按钮 //判断是否显示该按钮
const orderBtnsShow = (item) => { const orderBtnsShow = (item) => {
if(!orderInfo) return false if(!orderInfo) return false
if(item.id == 1) { if(item.id == 1) {
//取消退货 //取消退货
return (orderInfo.type == 1)&&item.value.includes(orderInfo.stage) return (orderInfo.type == 1)&&item.value.includes(orderInfo.stage)
@ -94,9 +91,14 @@ export default memo(({orderInfo, onClick}:Param) => {
//取消退款 //取消退款
return (orderInfo.type == 2)&&item.value.includes(orderInfo.stage) return (orderInfo.type == 2)&&item.value.includes(orderInfo.stage)
} else { } else {
return item.value.includes(orderInfo.stage) if(item.value.includes(orderInfo.stage)) {
return true
} else {
onBtnNull?.()
}
} }
} }
//显示的按钮数组 //显示的按钮数组

View File

@ -7,6 +7,7 @@ import {useRef, memo, useState, useMemo } from "react"
import classnames from "classnames"; import classnames from "classnames";
import styles from './index.module.scss' import styles from './index.module.scss'
import { AddShoppingCartApi } from "@/api/shopCart" import { AddShoppingCartApi } from "@/api/shopCart"
import { ApplyRefundApi } from "@/api/salesAfterOrder"
type Param = { type Param = {
orderInfo: { orderInfo: {
@ -133,6 +134,8 @@ export default memo(({orderInfo, onClick}:Param) => {
receiveOrder() receiveOrder()
} else if(val == 5) { } else if(val == 5) {
goLink('/pages/applyAfterSales/index',{id:orderInfo?.orderId}) goLink('/pages/applyAfterSales/index',{id:orderInfo?.orderId})
} else if(val == 8) {
applyRefund()
} else { } else {
onClick?.(val) onClick?.(val)
} }
@ -181,6 +184,28 @@ export default memo(({orderInfo, onClick}:Param) => {
}) })
} }
//退款
const {fetchData: fetchDataApplyRefund} = ApplyRefundApi()
const applyRefund = async () => {
Taro.showModal({
title: '确定退款?',
success: async function async (res) {
if(res.confirm) {
let res = await fetchDataApplyRefund({sale_order_id: orderInfo?.orderId})
if(res.success) {
alert.success('申请成功')
} else {
alert.error('申请失败')
}
onClick?.(8)
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
//显示更多按钮 //显示更多按钮
const [showMore, setShowMore] = useState(false) const [showMore, setShowMore] = useState(false)

View File

@ -67,7 +67,6 @@ export default () => {
unit: orderDetail.sale_mode == 0?'条':'m', //单位 unit: orderDetail.sale_mode == 0?'条':'m', //单位
list: orderDetail.product_list, list: orderDetail.product_list,
status: orderDetail.status, //订单状态 status: orderDetail.status, //订单状态
}) })
} }

View File

@ -192,9 +192,9 @@ export default (props:Params) => {
{ {
(!userInfo.adminUserInfo?.is_authorize_phone)&&<View className={styles.buy_btn} > (!userInfo.adminUserInfo?.is_authorize_phone)&&<View className={styles.buy_btn} >
<Button className={styles.phoneBtn} open-type="getPhoneNumber" onGetPhoneNumber={(e) => placeOrder('to_phone',e)}></Button> <Button className={styles.phoneBtn} open-type="getPhoneNumber" onGetPhoneNumber={(e) => placeOrder('to_phone',e)}></Button>
</View> </View>
|| <View className={styles.buy_btn} onClick={() => placeOrder('to_order')}></View> || <View className={styles.buy_btn} onClick={() => placeOrder('to_order')}></View>
} }
</View> </View>
<CustomWrapper> <CustomWrapper>

View File

@ -1,43 +1,76 @@
import Popup from "@/components/popup"; import Popup from "@/components/popup";
import TextareaEnhance from "@/components/textareaEnhance"; import TextareaEnhance from "@/components/textareaEnhance";
import { ScrollView, Text, View } from "@tarojs/components"; import { ScrollView, Text, View } from "@tarojs/components";
import { memo, useCallback, useState } from "react"; import { memo, useCallback, useEffect, useRef, useState } from "react";
import ReasonPopup from "../reasonPopup"; import ReasonPopup from "../reasonPopup";
import styles from './index.module.scss' import styles from './index.module.scss'
import classnames from "classnames"; import classnames from "classnames";
import { ApplyRefundApi } from "@/api/salesAfterOrder";
import { alert } from "@/common/common";
type Param = { type Param = {
show?: true|false, show?: true|false,
onClose?: () => void onClose?: () => void,
orderId?: number
} }
export default memo(({show, onClose}:Param) => { export default memo(({show, onClose, orderId}:Param) => {
//提交的数据
const getOtherReason = useCallback(() => { const submitData = useRef({
return_explain: 1,
sale_order_id: 0,
reason_describe: ''
})
}, []) useEffect(() => {
if(orderId)
const onSubmit = (val) => { submitData.current.sale_order_id = orderId
}, [orderId])
//申请退款
const {fetchData} = ApplyRefundApi()
const getApplyRefund = async () => {
let res = await fetchData(submitData.current)
if(!submitData.current.return_explain) return alert.error('请选择说明原因')
if(res.success) {
alert.error('申请成功')
} else {
alert.error('申请失败')
}
onClose?.()
} }
//获取说明数据
const [list, setList] = useState<any[]>([])
//备注
const getOtherReason = useCallback((val) => {
submitData.current.reason_describe = val
}, [])
//显示说明 //显示说明
const [showReason, setShowReason] = useState(false) const [showReason, setShowReason] = useState(false)
const closeReason = useCallback(() => { const closeReason = useCallback(() => {
setShowReason(false) setShowReason(false)
}, []) }, [])
const onShowReason = () => {
setShowReason(true) //提交
const onSubmit = () => {
getApplyRefund()
} }
return ( return (
<> <>
<Popup show={show} title="申请退款" onClose={onClose} > <Popup show={show} title="申请退款" onClose={onClose} >
<View className={styles.apply_after_sales_con}> <View className={styles.apply_after_sales_con}>
<View className={styles.returnSaleInput_item}> <View className={styles.returnSaleInput_item}>
<View className={styles.title}>退</View> <View className={styles.title}>退</View>
<View className={styles.select} onClick={() => onShowReason()}> <View className={styles.select} onClick={() => setShowReason(true)}>
<Text></Text> <Text></Text>
<Text className={classnames(styles.miconfont, 'iconfont icon-a-moreback')}></Text> <Text className={classnames(styles.miconfont, 'iconfont icon-a-moreback')}></Text>
</View> </View>
@ -51,7 +84,7 @@ export default memo(({show, onClose}:Param) => {
</View> </View>
</View> </View>
</Popup> </Popup>
<ReasonPopup show={showReason} onClose={closeReason} /> <ReasonPopup show={showReason} onClose={closeReason} list={list} title="退款说明"/>
</> </>
) )
}) })

View File

@ -22,6 +22,9 @@
.reason_item{ .reason_item{
margin-bottom: 36px; margin-bottom: 36px;
} }
.select_item {
color: #007AFF;
}
} }
} }
} }

View File

@ -1,34 +1,27 @@
import Popup from "@/components/popup"; import Popup from "@/components/popup";
import { ScrollView, Text, View } from "@tarojs/components"; import { ScrollView, Text, View } from "@tarojs/components";
import { memo, useMemo } from "react"; import { memo, useMemo } from "react";
import classnames from "classnames";
import styles from './index.module.scss' import styles from './index.module.scss'
//原因选择 //原因选择
type ReasonInfoParam = { type ReasonInfoParam = {
show?: boolean, show?: boolean, //显示
onClose?: () => void, onClose?: () => void, //关闭
title?: string, //标题
list?: {id:number, name:string, typle?:number}[], //数据列表
onSelect?: (val: object) => void, //选择
defaultValue?: number, //默认选中
} }
export default memo(({show = false, onClose}: ReasonInfoParam) => { export default memo(({show = false, onClose, title = '', list= [], onSelect, defaultValue}: ReasonInfoParam) => {
return ( return (
<Popup showIconButton={false} show={show} title="退款说明" onClose={onClose} > <Popup showIconButton={false} show={show} title={title} onClose={onClose} >
<View className={styles.reason_return_con}> <View className={styles.reason_return_con}>
<View className={styles.reason_title}><Text>退</Text></View> <View className={styles.reason_title}><Text>{title}</Text></View>
<ScrollView scrollY className={styles.reason_scroll}> <ScrollView scrollY className={styles.reason_scroll}>
<View className={styles.reason_list}> <View className={styles.reason_list}>
<View className={styles.reason_item}></View> {list.map(item => <View onClick={() => onSelect?.(item)} key={item.id} className={classnames(styles.reason_item, item.id == defaultValue&&styles.select_item)}>{item.name}</View> )}
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
<View className={styles.reason_item}></View>
</View> </View>
</ScrollView> </ScrollView>
</View> </View>

View File

@ -19,13 +19,13 @@ export default ({onBlur, onSave, defaultValue = ''}:Param) => {
getDesc(defaultValue) getDesc(defaultValue)
}, [defaultValue]) }, [defaultValue])
const getDesc = useCallback((value) => { const getDesc = (value) => {
let res = value let res = value
if(value.length > descData.count) { if(value.length > descData.count) {
res = value.slice(0, descData.count) res = value.slice(0, descData.count)
} }
setDescData({...descData, number:res.length, value: res}) setDescData({...descData, number:res.length, value: res})
},[]) }
const setSave = () => { const setSave = () => {
onSave?.(descData.value) onSave?.(descData.value)
@ -34,7 +34,7 @@ export default ({onBlur, onSave, defaultValue = ''}:Param) => {
<View className={styles.order_popup}> <View className={styles.order_popup}>
<View className={styles.order_popup_title}></View> <View className={styles.order_popup_title}></View>
<View className={styles.order_popup_input}> <View className={styles.order_popup_input}>
<Textarea placeholder="请添加备注" maxlength={descData.count} cursorSpacing={100} onInput={(e) => getDesc(e.detail.value)} onBlur={(e) => onBlur?.(e)}></Textarea> <Textarea placeholder="请添加备注" value={descData?.value} maxlength={descData.count} cursorSpacing={100} onInput={(e) => getDesc(e.detail.value)} onBlur={(e) => onBlur?.(e)}></Textarea>
<View className={styles.descDataNum}>{descData.number}/{descData.count}</View> <View className={styles.descDataNum}>{descData.number}/{descData.count}</View>
</View> </View>
<View className={styles.order_save_address} onClick={() => setSave()}></View> <View className={styles.order_save_address} onClick={() => setSave()}></View>

View File

@ -282,7 +282,7 @@ import styles from './index.module.scss'
<Remark onSave={(e) => getRemark(e)} defaultValue={orderDetail?.remark}/> <Remark onSave={(e) => getRemark(e)} defaultValue={orderDetail?.remark}/>
</Popup> </Popup>
<Payment onSubmitSuccess={onPaySuccess} show={payMentShow} onClose={closePayShow} orderInfo={orderDetail} /> <Payment onSubmitSuccess={onPaySuccess} show={payMentShow} onClose={closePayShow} orderInfo={orderDetail} />
<ApplyRefund show={refundShow} onClose={applyRefundClose}/> <ApplyRefund show={refundShow} onClose={applyRefundClose} orderId={orderDetail?.id}/>
<ShopCart show={showCart} onClose={() => setShowCart(false)}/> <ShopCart show={showCart} onClose={() => setShowCart(false)}/>
<View className="common_safe_area_y"></View> <View className="common_safe_area_y"></View>
</View> </View>

View File

@ -85,8 +85,8 @@ export default memo(({value, onClickBtn}: Param) => {
</View> </View>
<View className={styles.product_list}> <View className={styles.product_list}>
<View className={styles.image}> <View className={styles.image}>
<LabAndImg value={{lab:value.lab,rgb:value.rgb,texture_url:value.texture_url}}/> <LabAndImg value={{lab:value.lab,rgb:value.rgb,texture_url:value.texture_url}}/>
<View className={styles.color_num}>{value?.product_list[0].product_colors[0].code}</View> <View className={styles.color_num}>{value?.product_list[0].product_colors[0].code}</View>
</View> </View>
<View className={styles.color_list}> <View className={styles.color_list}>
{value?.product_list[0].product_colors.map((itemColor, index) => { {value?.product_list[0].product_colors.map((itemColor, index) => {

View File

@ -5,7 +5,7 @@ import {
import { GetOrderPayApi } from "@/api/orderPay"; import { GetOrderPayApi } from "@/api/orderPay";
import { SaleOrderOrderDetailApi } from "@/api/salesAfterOrder"; import { SaleOrderOrderDetailApi } from "@/api/salesAfterOrder";
import { alert, goLink } from "@/common/common"; import { alert, goLink } from "@/common/common";
import { ORDER_STATUS } from "@/common/enum"; import { AFTER_ORDER_STATUS, ORDER_STATUS } from "@/common/enum";
import { formatDateTime, formatImgUrl, formatPriceDiv } from "@/common/fotmat"; import { formatDateTime, formatImgUrl, formatPriceDiv } from "@/common/fotmat";
import AfterOrderBtns from "@/components/afterOrderBtns"; import AfterOrderBtns from "@/components/afterOrderBtns";
import OrderBtns from "@/components/orderBtns"; import OrderBtns from "@/components/orderBtns";
@ -95,8 +95,10 @@ import styles from './index.module.scss'
} }
}, [orderDetail]) }, [orderDetail])
//订单状态枚举 //售后订单状态枚举
const {SaleOrderStatusCancel} = ORDER_STATUS const {
} = AFTER_ORDER_STATUS
//物流显示 //物流显示
const [logisticsShow, setLogisticsShow] = useState(false) const [logisticsShow, setLogisticsShow] = useState(false)
@ -122,15 +124,17 @@ import styles from './index.module.scss'
//显示生气记录 //显示生气记录
const [applyRecord, setApplyRecord] = useState(false) const [applyRecord, setApplyRecord] = useState(false)
//货
return ( return (
<View className={styles.order_main}> <View className={styles.order_main}>
<OrderState orderInfo={orderDetail}/> <OrderState orderInfo={orderDetail}/>
<AddressInfoDetail return_address={orderDetail?.return_address} return_phone={orderDetail?.return_phone} stage={orderDetail?.stage} onLogistics={onShowLogistics}/> <AddressInfoDetail return_address={orderDetail?.return_address} return_phone={orderDetail?.return_phone} stage={orderDetail?.stage} onLogistics={onShowLogistics}/>
<KindList order={formatPreViewOrderMemo}/> <KindList order={formatPreViewOrderMemo}/>
<OrderDes orderInfo={orderDetail}/> <OrderDes orderInfo={orderDetail}/>
{(orderDetail?.status != SaleOrderStatusCancel.value)&&<View className={styles.submit_order}> <View className={styles.submit_order}>
<AfterOrderBtns orderInfo={orderInfo} onClick={orderStateClick}/> <AfterOrderBtns orderInfo={orderInfo} onClick={orderStateClick} />
</View>} </View>
<AfterSalePricture urls={orderDetail?.fabric_piece_accessory_url}/> <AfterSalePricture urls={orderDetail?.fabric_piece_accessory_url}/>
<ReturnLogistics show={logisticsShow} id={orderDetail?.return_apply_order_id} onClose={onCloseLogistics} onSubmit={logisticsSuccess}/> <ReturnLogistics show={logisticsShow} id={orderDetail?.return_apply_order_id} onClose={onCloseLogistics} onSubmit={logisticsSuccess}/>
<ApplyRecord show={applyRecord} id={orderDetail?.id} onClose={() => setApplyRecord(false)}/> <ApplyRecord show={applyRecord} id={orderDetail?.id} onClose={() => setApplyRecord(false)}/>

View File

@ -109,7 +109,7 @@ export default memo(({value, onClickBtn}: Param) => {
<Text>{value?.order_no}</Text> <Text>{value?.order_no}</Text>
</View> </View>
</View> </View>
<AfterOrderBtns orderInfo={orderInfo} onClick={orderBtnsClick}/> <AfterOrderBtns orderInfo={orderInfo} onClick={orderBtnsClick} />
</View> </View>
) )
}) })

View File

@ -107,7 +107,6 @@ export default () => {
const [logisticsShow, setLogisticsShow] = useState(false) const [logisticsShow, setLogisticsShow] = useState(false)
const onCloseLogistics = useCallback(() => setLogisticsShow(false), []) const onCloseLogistics = useCallback(() => setLogisticsShow(false), [])
return ( return (
<View className={styles.order_list_main}> <View className={styles.order_list_main}>
<View className={styles.title}> <View className={styles.title}>