mirror of
https://gitee.com/ShopeX/ECShopX_mobile-frontend
synced 2026-08-12 22:35:37 +08:00
Merge branch 'feature/ECX-7316' into 'master'
Feature/ecx 7316 See merge request huiqi/ecshopx-vshop!82
This commit is contained in:
@@ -15,7 +15,8 @@ function SpCheckboxNew(props) {
|
||||
|
||||
const [isChecked, setChecked] = useState(checked)
|
||||
|
||||
const onChangeCheckbox = () => {
|
||||
const onChangeCheckbox = (e) => {
|
||||
e.stopPropagation()
|
||||
if (disabled) return
|
||||
setChecked(!isChecked)
|
||||
onChange && onChange(!isChecked)
|
||||
@@ -23,7 +24,7 @@ function SpCheckboxNew(props) {
|
||||
|
||||
useEffect(() => {
|
||||
setChecked(props.checked)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View
|
||||
|
||||
@@ -14,4 +14,4 @@ export const SG_ROUTER_PARAMS = 'routerParams' // 路由参数缓存
|
||||
export const SG_GUIDE_PARAMS = 'guideParams' // 导购参数缓存
|
||||
export const SG_GUIDE_PARAMS_UPDATETIME = 'guideParams_updatetime' // 导购参数缓存时间戳
|
||||
export const SG_GUIDE_PARAMS_EXPRESSTIME = 'guideParams_expresstime' // 店铺参数保存时间
|
||||
export const SG_CHECK_STORE_RULE = 'check_store_rule' // 检查店铺进店规则
|
||||
export const SG_CHECK_STORE_RULE = 'check_store_rule' // 检查店铺进店规则
|
||||
@@ -120,6 +120,7 @@ export const SHOP_INFO = {
|
||||
}
|
||||
|
||||
export const AFTER_TRADE = {
|
||||
aftersalesAddress: 'aftersales_address',
|
||||
aftersalesBn: 'aftersales_bn',
|
||||
aftersalesStatus: 'aftersales_status',
|
||||
createdTime: ({ create_time }) => formatDateTime(create_time * 1000),
|
||||
@@ -141,6 +142,7 @@ export const AFTER_TRADE = {
|
||||
refundFee: ({ refund_fee }) => refund_fee / 100,
|
||||
userId: 'user_id',
|
||||
freight: ({ freight }) => freight / 100,
|
||||
progress: 'progress',
|
||||
}
|
||||
|
||||
export const TRADE_AFTER_SALES_ITEM = {
|
||||
@@ -156,8 +158,8 @@ export const TRADE_AFTER_SALES_ITEM = {
|
||||
pic: ({ orderItem }) => orderItem.pic,
|
||||
itemName: ({ orderItem }) => orderItem.item_name,
|
||||
itemSpecDesc: ({ orderItem }) => orderItem.item_spec_desc,
|
||||
num: ({ orderItem }) => orderItem.refundNum,
|
||||
price: ({ orderItem }) => orderItem.total_fee / 100,
|
||||
num: 'num',
|
||||
price: ({ refund_fee, num }) => (refund_fee / num) / 100,
|
||||
isPrescription: ({ orderItem }) => orderItem.is_prescription,
|
||||
})
|
||||
},
|
||||
@@ -170,8 +172,9 @@ export const TRADE_AFTER_SALES_ITEM = {
|
||||
refundFee: ({ refund_fee }) => refund_fee / 100,
|
||||
refund_info: ({ refund_info }) => {
|
||||
return pickBy(refund_info, {
|
||||
refundFee: ({ refunded_fee }) => refunded_fee / 100,
|
||||
refundFee: ({ refund_fee }) => refund_fee / 100,
|
||||
refundPoint: 'refund_point',
|
||||
freight: ({ freight }) => freight / 100
|
||||
})
|
||||
},
|
||||
refundPoint: 'refund_point',
|
||||
|
||||
@@ -195,7 +195,7 @@ function TradeAfterSaleDetail(props) {
|
||||
</View>
|
||||
<View className='goods-info-bd'>
|
||||
<View>{item.itemSpecDesc && <Text className='sku-info'>{`${item.itemSpecDesc}`}</Text>}</View>
|
||||
<View><SpPrice size={28} value={item.price / item.num} /> x <Text className='num'>{item.num}</Text></View>
|
||||
<View><SpPrice size={28} value={item.price} /> x <Text className='num'>{item.num}</Text></View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -206,7 +206,7 @@ function TradeAfterSaleDetail(props) {
|
||||
</View>
|
||||
<View className='goods-info-bd'>
|
||||
<View>{item.itemSpecDesc && <Text className='sku-info'>{`${item.itemSpecDesc}`}</Text>}</View>
|
||||
<View><SpPrice size={28} value={item.price / item.num} /> x <Text className='num'>{item.num}</Text></View>
|
||||
<View><SpPrice size={28} value={item.price} /> x <Text className='num'>{item.num}</Text></View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@@ -224,9 +224,9 @@ function TradeAfterSaleDetail(props) {
|
||||
<SpCell title='退积分' value={<SpPrice value={info?.refund_info?.refundPoint || info?.refundPoint} />}></SpCell>
|
||||
</View>
|
||||
{
|
||||
info?.refund_freight_amount > 0 &&
|
||||
info?.refund_info?.freight > 0 &&
|
||||
<View className='refund-point'>
|
||||
<SpCell title='退运费' value={info?.refund_freight_amount}></SpCell>
|
||||
<SpCell title='退运费' value={info?.refund_info?.freight}></SpCell>
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
|
||||
@@ -4,7 +4,7 @@ import Taro, { useRouter } from '@tarojs/taro'
|
||||
import { View, ScrollView } from '@tarojs/components'
|
||||
import { AtButton } from 'taro-ui'
|
||||
import { useImmer } from 'use-immer'
|
||||
import { SpPage, SpTagBar, SpScrollView } from '@/components'
|
||||
import { SpPage, SpTagBar, SpScrollView, SpSearchBar } from '@/components'
|
||||
import api from '@/api'
|
||||
import doc from '@/doc'
|
||||
import { pickBy } from '@/utils'
|
||||
@@ -23,13 +23,22 @@ const initialState = {
|
||||
status: '0',
|
||||
typeVal:'0',
|
||||
tradeList: [],
|
||||
refresherTriggered: false
|
||||
refresherTriggered: false,
|
||||
order_id: '',
|
||||
selectAftersn: []
|
||||
}
|
||||
function TradeAfterSaleList(props) {
|
||||
const [state, setState] = useImmer(initialState)
|
||||
const { tradeStatus, status, tradeList, refresherTriggered, typeVal } = state
|
||||
const {
|
||||
tradeStatus,
|
||||
status,
|
||||
tradeList,
|
||||
refresherTriggered,
|
||||
typeVal,
|
||||
order_id,
|
||||
selectAftersn
|
||||
} = state
|
||||
const tradeRef = useRef()
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
// 撤销售后事件
|
||||
@@ -57,7 +66,8 @@ function TradeAfterSaleList(props) {
|
||||
page: pageIndex,
|
||||
pageSize,
|
||||
order_type: 'normal',
|
||||
aftersales_status: status
|
||||
aftersales_status: status,
|
||||
order_id
|
||||
}
|
||||
// params.order_class = typeVal == '1' ? 'employee_purchase' : 'normal'
|
||||
const { list, total_count } = await api.aftersales.list(params)
|
||||
@@ -72,6 +82,7 @@ function TradeAfterSaleList(props) {
|
||||
const onChangeTradeState = (e) => {
|
||||
setState((draft) => {
|
||||
draft.status = tradeStatus[e].value
|
||||
draft.selectAftersn = []
|
||||
})
|
||||
}
|
||||
|
||||
@@ -90,8 +101,78 @@ function TradeAfterSaleList(props) {
|
||||
})
|
||||
}
|
||||
|
||||
const handleOnChange = (val) => {
|
||||
setState((v) => {
|
||||
v.order_id = val
|
||||
})
|
||||
}
|
||||
|
||||
const handleOnClear = () => {
|
||||
setState((v) => {
|
||||
v.order_id = ''
|
||||
v.tradeList = []
|
||||
})
|
||||
tradeRef.current.reset()
|
||||
}
|
||||
|
||||
const handleConfirm = async (val) => {
|
||||
setState((v) => {
|
||||
v.tradeList = []
|
||||
v.order_id = val
|
||||
})
|
||||
await tradeRef.current.reset()
|
||||
}
|
||||
|
||||
const onSelect = (sn) => {
|
||||
let list = [...selectAftersn]
|
||||
const index = list.indexOf(sn)
|
||||
if (index > -1) {
|
||||
list.splice(index, 1)
|
||||
} else {
|
||||
list.push(sn)
|
||||
}
|
||||
setState((draft) => {
|
||||
draft.selectAftersn = list
|
||||
})
|
||||
}
|
||||
|
||||
const onSubmit = () => {
|
||||
console.log(tradeList,selectAftersn)
|
||||
const fliterList = tradeList?.filter((item) => selectAftersn.includes(item.aftersalesBn) && item.aftersalesAddress)
|
||||
debugger
|
||||
const address = fliterList[0].aftersalesAddress
|
||||
Taro.setStorageSync('moreAftersalesBn', {
|
||||
aftersalesBn: selectAftersn,
|
||||
address
|
||||
})
|
||||
Taro.navigateTo({ url: `/subpages/trade/logistics-info?type=more` })
|
||||
}
|
||||
|
||||
const renderFooter = () => {
|
||||
if (status != '1') return null
|
||||
return (
|
||||
<View className='btn-wrap'>
|
||||
<AtButton circle type='primary' disabled={selectAftersn.length === 0} onClick={onSubmit}>批量处理</AtButton>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<SpPage className='page-trade-aftersale-list'>
|
||||
<SpPage
|
||||
className='page-trade-aftersale-list'
|
||||
renderFooter={renderFooter()}
|
||||
>
|
||||
<View className='search-bar-container'>
|
||||
<SpSearchBar
|
||||
keyword={order_id}
|
||||
placeholder='请输入订单号'
|
||||
showDailog={false}
|
||||
onChange={handleOnChange}
|
||||
onClear={handleOnClear}
|
||||
onCancel={handleOnClear}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
</View>
|
||||
<CompTrackType value={typeVal} onChange={onChangeTradeType} />
|
||||
<SpTagBar list={tradeStatus} value={status} onChange={onChangeTradeState} />
|
||||
<ScrollView
|
||||
@@ -111,7 +192,12 @@ function TradeAfterSaleList(props) {
|
||||
>
|
||||
{tradeList.map((item, index) => (
|
||||
<View className='trade-item-wrap' key={index}>
|
||||
<CompAfterTradeItem info={item} />
|
||||
<CompAfterTradeItem
|
||||
info={item}
|
||||
selectAftersn={selectAftersn}
|
||||
isShowChecked={status == '1' && item.progress == 1}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
</View>
|
||||
))}
|
||||
</SpScrollView>
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
$tag-bar-height: 90px;
|
||||
|
||||
.page-trade-aftersale-list {
|
||||
.search-bar-container {
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
}
|
||||
.sp-tag-bar {
|
||||
background: #f5f5f5;
|
||||
height: $tag-bar-height;
|
||||
@@ -23,5 +27,11 @@ $tag-bar-height: 90px;
|
||||
}
|
||||
.comp-tradeitem .shop-info .shop-name {
|
||||
width: 400px;
|
||||
}
|
||||
}
|
||||
.btn-wrap {
|
||||
width: 80%;
|
||||
// display: flex;
|
||||
// justify-content: end;
|
||||
margin: 20px auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,17 @@ import { useSelector } from 'react-redux'
|
||||
import Taro from '@tarojs/taro'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import { AtButton } from 'taro-ui'
|
||||
import { SpImage, SpPrice, SpTradeItem } from '@/components'
|
||||
import { SpImage, SpPrice, SpTradeItem, SpCheckboxNew } from '@/components'
|
||||
import { VERSION_STANDARD } from '@/utils'
|
||||
import { AFTER_SALE_STATUS } from '@/consts'
|
||||
import './comp-aftertrade-item.scss'
|
||||
|
||||
function CompTradeItem(props) {
|
||||
const { info } = props
|
||||
const { info, isShowChecked = false, selectAftersn = [], onSelect = () => {} } = props
|
||||
if (!info) {
|
||||
return null
|
||||
}
|
||||
const { aftersalesBn, distributorInfo, orderId, createdTime, aftersalesStatus, items, orderStatus, refundFee, orderClass = 'normal', point, distributorId ,freight} = info
|
||||
const { aftersalesBn, distributorInfo, createdTime, aftersalesStatus, items, orderStatus, refundFee, orderClass = 'normal', point, distributorId ,freight} = info
|
||||
// const { pointName } = useSelector((state) => state.sys)
|
||||
|
||||
|
||||
@@ -40,22 +40,20 @@ function CompTradeItem(props) {
|
||||
<View className='comp-tradeitem'>
|
||||
<View className='trade-item-hd' onClick={onViewTradeDetail}>
|
||||
<View>
|
||||
{/* <View className='shop-info' onClick={onViewStorePage}>
|
||||
<SpImage src={distributorInfo?.logo} width={100} height={100} />
|
||||
<View className='shop-name'>{distributorInfo?.name}{!VERSION_STANDARD && <Text className='iconfont icon-qianwang-01'></Text>}</View>
|
||||
</View> */}
|
||||
<View className='shop-info' onClick={onViewStorePage}>
|
||||
{/* <SpImage src={distributorInfo?.logo} width={100} height={100} /> */}
|
||||
{isShowChecked && <SpCheckboxNew checked={selectAftersn.includes(aftersalesBn)} style={{ marginRight: 24 }} onChange={() => onSelect(aftersalesBn)} />}
|
||||
<View className={`shop-name ${isShowChecked ? '' : 'nochecked'}`}>{distributorInfo?.name}{!VERSION_STANDARD && <Text className='iconfont icon-qianwang-01'></Text>}</View>
|
||||
</View>
|
||||
<View className='trade-no'>{`退款单号: ${aftersalesBn}`}</View>
|
||||
<View className='trade-time'>{`申请时间: ${createdTime}`}</View>
|
||||
</View>
|
||||
<View className='trade-state'>{AFTER_SALE_STATUS[aftersalesStatus]}</View>
|
||||
</View>
|
||||
<View className='trade-item-bd' onClick={onViewTradeDetail}>
|
||||
{items.map((good) => (
|
||||
<SpTradeItem info={{
|
||||
...good,
|
||||
}} />
|
||||
{items.map((good, goodIns) => (
|
||||
<SpTradeItem key={goodIns} info={{ ...good }} />
|
||||
))}
|
||||
|
||||
<View className='trade-total'>
|
||||
<View className='delivery'></View>
|
||||
{/* {
|
||||
@@ -74,10 +72,6 @@ function CompTradeItem(props) {
|
||||
}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='trade-item-ft'>
|
||||
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -68,18 +68,20 @@
|
||||
|
||||
.shop-info {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
|
||||
.sp-image {
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.nochecked {
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
font-size: 30px;
|
||||
color: #111;
|
||||
font-weight: bold;
|
||||
margin-left: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
|
||||
@@ -4,23 +4,26 @@ import Taro, { getCurrentInstance } from '@tarojs/taro'
|
||||
import { AtButton } from 'taro-ui'
|
||||
import api from '@/api'
|
||||
import S from '@/spx'
|
||||
import { View, Picker } from '@tarojs/components'
|
||||
import { View, Picker, Text } from '@tarojs/components'
|
||||
import { LOGISTICS_CODE } from '@/consts'
|
||||
import { SpPage, SpCell, SpInput as AtInput, SpToast } from '@/components'
|
||||
import { showToast } from '@/utils'
|
||||
import { showToast, copyText } from '@/utils'
|
||||
import './logistics-info.scss'
|
||||
|
||||
const initialState = {
|
||||
logi_no: '',
|
||||
corpIndex: 0,
|
||||
expressList: []
|
||||
expressList: [],
|
||||
afterInfo: null
|
||||
}
|
||||
function TradeLogisticsInfo(props) {
|
||||
const $instance = getCurrentInstance()
|
||||
const [state, setState] = useImmer(initialState)
|
||||
const { logi_no, expressList, corpIndex } = state
|
||||
const { logi_no, expressList, corpIndex, afterInfo } = state
|
||||
const { item_id, order_id, aftersales_bn, type = 'single' } = $instance.router.params
|
||||
|
||||
useEffect(() => {
|
||||
const aftersInfo = Taro.getStorageSync('moreAftersalesBn') || null
|
||||
const _expressList = Object.keys(LOGISTICS_CODE).map((key) => {
|
||||
return {
|
||||
name: LOGISTICS_CODE[key],
|
||||
@@ -29,11 +32,15 @@ function TradeLogisticsInfo(props) {
|
||||
})
|
||||
setState((draft) => {
|
||||
draft.expressList = _expressList
|
||||
draft.afterInfo = aftersInfo
|
||||
})
|
||||
return () => {
|
||||
Taro.removeStorageSync('moreAftersalesBn')
|
||||
}
|
||||
}, [])
|
||||
|
||||
const onSubmit = async () => {
|
||||
const { item_id, order_id, aftersales_bn } = $instance.router.params
|
||||
const aftersInfo = Taro.getStorageSync('moreAftersalesBn') || null
|
||||
const corp_code = expressList[corpIndex]?.code
|
||||
if (!corp_code) {
|
||||
showToast('请填写物流公司')
|
||||
@@ -47,10 +54,11 @@ function TradeLogisticsInfo(props) {
|
||||
await api.aftersales.sendback({
|
||||
item_id,
|
||||
order_id,
|
||||
aftersales_bn,
|
||||
aftersales_bn: aftersales_bn,
|
||||
logi_no,
|
||||
corp_code,
|
||||
showError:false
|
||||
showError:false,
|
||||
aftersales_data: aftersInfo?.aftersalesBn
|
||||
})
|
||||
showToast('操作成功')
|
||||
setTimeout(() => {
|
||||
@@ -87,6 +95,21 @@ function TradeLogisticsInfo(props) {
|
||||
</View>
|
||||
}
|
||||
>
|
||||
{type == 'more' && <View className='after-address'>
|
||||
<SpCell title='回寄信息:'>
|
||||
<>
|
||||
<View className='contact-mobile'>
|
||||
<Text className='contact'>{afterInfo?.address?.aftersales_contact}</Text>
|
||||
<Text className='mobile'>{afterInfo?.address?.aftersales_mobile}</Text>
|
||||
</View>
|
||||
<View className='btn-copy' circle size='small' onClick={() => {
|
||||
copyText(`${afterInfo?.address?.aftersales_contact} ${afterInfo?.address?.aftersales_mobile}\n${afterInfo?.address?.aftersales_address}`)
|
||||
}}>复制</View>
|
||||
</>
|
||||
</SpCell>
|
||||
<View className='address-detail'>{afterInfo?.address?.aftersales_address}</View>
|
||||
</View>
|
||||
}
|
||||
<SpCell
|
||||
className='logistics-company'
|
||||
title='物流公司'
|
||||
|
||||
@@ -1,4 +1,55 @@
|
||||
.page-trade-logistics-info {
|
||||
.after-address {
|
||||
margin: 24px 16px 0;
|
||||
padding: 24px 0;
|
||||
border-radius: 16px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
.sp-cell {
|
||||
align-items: flex-start;
|
||||
padding: 0 30px;
|
||||
}
|
||||
.sp-cell__title {
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
}
|
||||
.sp-cell__bd {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
.contact {
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
word-break: break-all;
|
||||
}
|
||||
.mobile {
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
color: #999;
|
||||
// margin-left: 20px;
|
||||
}
|
||||
}
|
||||
.sp-cell__ft,
|
||||
.sp-cell__link {
|
||||
display: none;
|
||||
}
|
||||
.address-detail {
|
||||
color: #222222;
|
||||
padding: 0 30px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.btn-container {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 32px;
|
||||
padding: 0 30px;
|
||||
}
|
||||
.btn-logistics {
|
||||
width: 210px;
|
||||
}
|
||||
}
|
||||
.btn-wrap {
|
||||
padding: 20px;
|
||||
}
|
||||
@@ -28,4 +79,9 @@
|
||||
.sp-input{
|
||||
text-align: right;
|
||||
}
|
||||
.address-detail {
|
||||
padding: 24px 32px;
|
||||
padding-top: 0;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user