794 lines
23 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { View } from '@tarojs/components'
import Taro, { useDidShow, usePullDownRefresh, useRouter } from '@tarojs/taro'
import type { ReactNode } from 'react'
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import classnames from 'classnames'
import styles from './index.module.scss'
import AddressDetailBox from './components/addressDetailBox'
import GoodsItem from './components/GoodsItem'
import Remark from '@/components/textareaEnhance'
import Popup from '@/components/popup'
import { debounce } from '@/common/util'
import {
MpSaleOrder,
MpSaleOrderPut,
MpsaleOrderaddProductList,
MpsaleOrdersubmit,
} from '@/api/order'
import { alert, goLink } from '@/common/common'
import { formatDateTime, formatHashTag, formatPriceDiv, formatRemoveHashTag, formatWeightDiv } from '@/common/format'
import { MpPurchaserAddressList } from '@/api/addressList'
// 卡片盒子元素
interface Obs {
title?: string
modeName?: string
showMode?: boolean
children?: ReactNode
clickNode?: () => void
}
const DefaultBox = (props: Obs) => {
const {
title = '标题',
modeName = '大货',
showMode = false,
children,
clickNode,
} = props
return (
<View className={styles.defaltBox}>
<View className={styles.titleBox}>
<View className={styles.title}>{title}</View>
{
showMode && <View className={styles.modeName} onClick={() => clickNode?.()}>{modeName}</View>
}
</View>
<View className={styles.modeLine}></View>
{children}
</View>
)
}
const DefaultBoxWithMemo = memo(DefaultBox)
const OrderDetails = () => {
const router = useRouter()
const addrssRef = useRef<any>([])
const pages = Taro.getCurrentPages()
const currPage = pages[pages.length - 1] // 获取当前页面
const { fetchData: addressFetch } = MpPurchaserAddressList()
let selectId = -1
// 收货方法,1:自提2物流
const [receivingStatus, setReceivingStatus] = useState<any>(null)
// 切换自提或者物流
const onReceivingStatus = debounce(async(e, value) => {
e.stopPropagation()
if (receivingStatus === value) {
alert.error('不能选择相同的方式')
return false
}
Taro.showLoading({
title: '请稍等...',
mask: true,
})
// 判断是否有默认地址
if (value === 2 && addrssRef.current.length > 0 && !currPage.data?.addressObj) {
setInfoObj(val => ({
...val,
province_name: addrssRef.current[0]?.province_name,
address_id: addrssRef.current[0]?.id,
city_name: addrssRef.current[0]?.city_name,
address_detail: addrssRef.current[0]?.address_detail,
district_name: addrssRef.current[0]?.district_name,
target_user_name: addrssRef.current[0]?.name,
purchaser_phone: addrssRef.current[0]?.phone,
}))
}
// 没有默认地址提示进去选择地址
if (value === 2 && !addrssRef.current.length && !infoObj?.address_id) {
alert.error('请选择地址')
}
setReceivingStatus(value)
Taro.hideLoading()
}, 300)
// 获取客户地址
// 获取地址
const getAddress = async(id) => {
const result = await addressFetch({ purchaser_id: id })
addrssRef.current = result?.data?.list.filter((item) => { return item.is_default })
}
const { fetchData: infoFetch } = MpSaleOrder()
const [infoObj, setInfoObj] = useState<any>({})
const [goodList, setgoodList] = useState<any>([])
// 获取订单详情
const getDetail = async() => {
Taro.showLoading({
title: '加载中...',
mask: true,
})
const res = await infoFetch({ id: router.params.orderId })
setInfoObj(res.data)
res.data.product_list.forEach((item) => {
item.product_colors.map((it) => {
it.nums = res.data?.sale_mode == 0 ? it.roll : it.length / 100
return it
})
})
setgoodList([...res.data.product_list])
orderMsg.map((it) => {
if (it.leftTitle === '订单编号:') {
it.rightTitle = res.data.order_no
}
if (it.leftTitle === '创建时间:') {
it.rightTitle = formatDateTime(res.data.create_time)
}
if (it.leftTitle === '发货时间:') {
it.rightTitle = formatDateTime(res.data.delivery_time)
}
if (it.leftTitle === '业务员:') {
it.rightTitle = res.data.sale_user_name
}
})
setOrderMsg([...orderMsg])
setReceivingStatus(res.data.shipment_mode)
// 小程序提供的api通知页面停止下拉刷新效果
Taro.stopPullDownRefresh()
Taro.hideLoading()
getAddress(res.data?.purchaser_id)
}
// 订单信息文字数组
const [orderMsg, setOrderMsg] = useState<any[]>([
{
leftTitle: '订单编号:',
rightTitle: '------',
showBtn: true,
},
{
leftTitle: '创建时间:',
rightTitle: '------',
},
{
leftTitle: '发货时间:',
rightTitle: '------',
},
{
leftTitle: '业务员:',
rightTitle: '------',
},
])
// 备注操作
const [showDesc, setShowDesc] = useState(false)
const { fetchData: remarkFetch } = MpSaleOrderPut()
const getRemark = async() => {
const res = await remarkFetch({ remark: infoObj.remark, id: Number(router.params.orderId) })
if (res.msg === 'success') {
Taro.showToast({
title: '成功',
icon: 'success',
})
setShowDesc(false)
getDetail()
}
}
useEffect(() => {
getDetail()
}, [])
// 面料修改获取金额列表接口
const { fetchData: editFetch } = MpsaleOrderaddProductList()
useDidShow(() => {
// getDetail()
const pages = Taro.getCurrentPages()
const currPage = pages[pages.length - 1] // 获取当前页面
// 获取选择回来的地址
if (currPage.data?.addressObj) {
setInfoObj(val => ({
...val,
province_name: currPage.data?.addressObj?.province_name ? currPage.data?.addressObj?.province_name : '',
address_id: currPage.data?.addressObj?.id ? currPage.data?.addressObj?.id : '',
city_name: currPage.data?.addressObj?.city_name ? currPage.data?.addressObj?.city_name : '',
address_detail: currPage.data?.addressObj?.address_detail ? currPage.data?.addressObj?.address_detail : '',
district_name: currPage.data?.addressObj?.district_name ? currPage.data?.addressObj?.district_name : '',
target_user_name: currPage.data?.addressObj?.name ? currPage.data?.addressObj?.name : '',
purchaser_phone: currPage.data?.addressObj?.phone ? currPage.data?.addressObj?.phone : '',
}))
}
selectId = currPage.data?.addressObj?.id
const obj = currPage?.data?.ids?.filter((item) => { return item == selectId })
if (currPage?.data?.ids && obj.length === 0 && infoObj?.address_id == 0) {
setInfoObj(val => ({
...val,
province_name: '',
address_id: '',
city_name: '',
address_detail: '',
district_name: '',
target_user_name: '',
purchaser_phone: '',
}))
}
if (!currPage.data?.addressObj && infoObj?.address_id == 0) {
setReceivingStatus(1)
}
else {
setReceivingStatus(2)
}
// 获取选择回来的商品
if (currPage.data?.selectGoodsList && currPage.data?.selectGoodsList.length > 0) {
for (let i = 0; i < currPage.data?.selectGoodsList.length; i++) {
let flag = true
for (let j = 0; j < goodList.length; j++) {
if (goodList[j].id === currPage.data?.selectGoodsList[i].id) {
flag = false
goodList[j].product_colors.push(...currPage.data?.selectGoodsList[i].product_colors)
}
}
if (flag) { goodList.push(currPage.data?.selectGoodsList[i]) }
}
handEditMoney(1)
}
})
const goodsObjRef = useRef<any>()
useEffect(() => {
goodsObjRef.current = goodList
}, [goodList])
// 面料修改或者添加获取实时金额
const handEditMoney = async(toastEnum) => {
let toastMsg = ''
if (toastEnum == 1) {
toastMsg = '添加商品成功'
}
else {
toastMsg = '修改商品成功'
}
Taro.showLoading({
title: '请稍等...',
})
const arr: any = []
goodsObjRef.current.forEach((ec) => {
ec.product_colors.forEach((v) => {
const colorsArr: any[] = []
colorsArr.push({
product_color_id: v.id,
length: infoObj?.sale_mode == 0 ? 0 : Number(v.nums) * 100,
roll: infoObj?.sale_mode != 0 ? 0 : Number(v.nums),
sale_price: v.sale_price,
})
arr.push({
product_id: ec.id,
sale_mode: Number(infoObj?.sale_mode),
color_list: colorsArr,
})
})
})
// 合并相同的数据
const idArray: any[] = []
const newAarray: any[] = []
arr.forEach((ele, i) => {
if (!idArray.includes(ele.product_id)) {
newAarray.push({
product_id: ele.product_id,
name: ele.name,
sale_mode: Number(infoObj?.sale_mode),
color_list: ele.color_list,
})
idArray.push(ele.product_id)
}
else {
newAarray.map((dom, k) => {
if (dom.product_id == ele.product_id) {
dom.color_list = [...ele.color_list, ...dom.color_list]
}
})
}
})
const res = await editFetch({ add_product_list_param: newAarray, sale_order_id: infoObj?.id })
if (res.data) {
Taro.hideLoading()
Taro.showToast({
title: toastMsg,
icon: 'none',
})
goodList.map((item) => {
res.data.list?.map((v) => {
if (item.id == v.id) {
item.product_colors?.forEach((edg) => {
v.product_colors?.forEach((ac) => {
if (edg.id == ac.id) {
edg.total_sale_price = ac.total_sale_price
}
})
})
}
})
return item
})
setgoodList([...goodList])
}
else {
Taro.hideLoading()
}
}
// 页面下拉刷新
usePullDownRefresh(() => {
getDetail()
})
// 选择地址
const handSelect = (obj) => {
Taro.navigateTo({
url: `/pages/addressManager/index?orderId=${-100}&purchaser_id=${obj.purchaser_id}`,
})
}
// 是否显示按钮
const showBtn = useMemo(() => {
if ((infoObj.status === 8 || infoObj.status === 9 || infoObj.status === 4 || infoObj.status === 5 || infoObj.status === 11 || infoObj.status === 3)) {
return false
}
else {
return true
}
}, [infoObj])
const showWhatFont = useMemo(() => {
if (infoObj.shipment_mode === 1) {
return '自提商品'
}
else {
return '物流'
}
}, [infoObj])
const onChange = (e) => {
setInfoObj(val => ({ ...val, remark: e }))
}
useEffect(() => {
setInfoObj(infoObj)
}, [infoObj])
const showRemarkFont = useMemo(() => {
if (infoObj.status === 10 || infoObj.status == 0 || infoObj.status == 1 || infoObj.status == 2 || infoObj.status == 7) {
return `${'填写/修改备注'} >`
}
else {
return ''
}
}, [infoObj])
// 待接单、配布中、已配布状态时,叫预估金额,其他状态叫合计金额。
const payFont = useMemo(() => {
if (infoObj?.status === 0 || infoObj?.status === 1 || infoObj?.status === 2) {
return '预估金额'
}
else {
return '合计金额'
}
}, [infoObj])
// 复制功能
const clipboardData = () => {
Taro.setClipboardData({
data: infoObj?.order_no || '',
success(res) {
Taro.showToast({
icon: 'none',
title: '复制成功',
})
},
})
}
// 判断是否整数类型
function isInteger(obj) {
return (obj | 0) === obj
}
// 删除面料的ids数组
const [deleteProductIds, setdeleteProductIds] = useState<any[]>([])
// 删除商品弹窗
const handCancelToast = (item) => {
// const deletIds: any[] = []
for (let i = 0; i < goodList?.length; i++) {
if (goodList.length === 1 && goodList[i].product_colors?.length === 1) {
return Taro.showToast({
icon: 'none',
title: '至少保留一个面料',
})
}
}
Taro.showModal({
content: '删除所选商品?',
async success(res) {
if (res.confirm) {
// 删除某项商品
goodList.forEach((edg) => {
edg?.product_colors.map((it, index) => {
if (item.id == it.id) {
deleteProductIds.push(item.id)
edg?.product_colors.splice(index, 1)
}
return it
})
return edg
})
// 子商品没有了大商品也删除
goodList.forEach((edg, index) => {
if (!edg?.product_colors.length) {
goodList.splice(index, 1)
}
})
setgoodList([...goodList])
setdeleteProductIds([...deleteProductIds])
}
else if (res.cancel) {
console.log('用户点击取消')
}
},
})
}
// 输入框减
const clickReduce = useCallback((item) => {
goodList.forEach((edg) => {
edg?.product_colors.map((it) => {
if (item.id == it.id) {
if (infoObj?.sale_mode == 0 && item.nums == 1) {
return handCancelToast(item)
}
if (infoObj?.sale_mode == 1 && item.nums == 0.3) {
return handCancelToast(item)
}
if (infoObj?.sale_mode == 2 && item.nums == 3) {
return handCancelToast(item)
}
if (isInteger(item.nums)) {
it.nums--
handEditMoney(2)
}
else {
it.nums = Math.trunc(item.nums)
handEditMoney(2)
}
}
return it
})
return edg
})
setgoodList([...goodList])
// if ((infoObj?.sale_mode == 0 && item.nums > 1) || (infoObj?.sale_mode == 1 && item.nums > 0.3) || (infoObj?.sale_mode == 2 && item.nums > 3)) {
// handEditMoney(2)
// }
}, [goodList])
// 输入框加
const handPlus = useCallback((item) => {
goodList.forEach((edg) => {
edg?.product_colors.map((it) => {
if (item.id == it.id) {
if (isInteger(item.nums)) {
item.nums++
}
else {
item.nums++
item.nums = Math.trunc(item.nums)
}
}
return it
})
return edg
})
setgoodList([...goodList])
handEditMoney(2)
}, [goodList])
// 输入框监听
const onBlur = useCallback((e, item) => {
goodList.forEach((edg) => {
edg?.product_colors.map((it) => {
if (it.id == item.id) {
if (infoObj.sale_mode == 0 && (e.detail.value == '' || Number(e.detail.value) == 0)) {
it.nums = 1
}
else if (infoObj.sale_mode == 0 && (e.detail.value != '' || Number(e.detail.value) > 0)) {
it.nums = Number(e.detail.value)
}
if (infoObj.sale_mode == 1 && Number(e.detail.value) < 0.3) {
it.nums = 0.3
}
else if (infoObj.sale_mode == 1 && Number(e.detail.value) >= 0.3) {
if (isInteger(Number(e.detail.value))) {
it.nums = Number(e.detail.value)
}
else {
it.nums = Number(e.detail.value).toFixed(2)
}
}
if (infoObj.sale_mode == 2 && Number(e.detail.value) < 3) {
it.nums = 3
}
else if (infoObj.sale_mode == 2 && Number(e.detail.value) >= 3) {
if (isInteger(Number(e.detail.value))) {
it.nums = Number(e.detail.value)
}
else {
it.nums = Number(e.detail.value).toFixed(2)
}
}
}
return it
})
return edg
})
setgoodList([...goodList])
handEditMoney(2)
}, [goodList])
// 添加面料
const navTo = () => {
const arr = JSON.stringify(goodList).replace(/%/g, '%25')
Taro.navigateTo({
url: `/pages/addFabric/index?goodList=${arr}&purchaser_id=${infoObj?.purchaser_id}&sale_mode=${infoObj?.sale_mode}`,
})
}
const { fetchData: submitFetch } = MpsaleOrdersubmit()
// 提交修改
const handSubmit = () => {
if ((infoObj?.address_id == 0 || !infoObj?.address_id) && receivingStatus == 2) {
return Taro.showToast(
{
title: '请选择收货地址',
icon: 'error',
},
)
}
const quertArr: any[] = []
goodList.forEach((item) => {
item.product_colors?.forEach((edc) => {
quertArr.push({
length: infoObj?.sale_mode != 0 ? edc.nums * 100 : 0,
product_color_id: edc.id,
product_id: item.id,
roll: infoObj?.sale_mode == 0 ? edc.nums : 0,
// sale_order_detail_id: edc.sale_order_detail_id ? edc.sale_order_detail_id : 0,
})
})
})
const query = {
address_id: infoObj?.address_id,
commodity_list: quertArr,
delete_detail_list: filterArr(deleteProductIds),
remark: infoObj?.remark,
sale_order_id: infoObj?.id,
shipment_mode: receivingStatus,
}
console.log(query, 'quertArrquertArr')
Taro.showModal({
content: '是否确认提交修改',
async success(res) {
if (res.confirm) {
Taro.showLoading({
title: '加载中...',
})
const res = await submitFetch(query)
if (res.data) {
Taro.hideLoading()
Taro.redirectTo({
url: `/pages/orderDetails/index?id=${res.data.id}`,
})
}
else {
Taro.showToast({
title: res.data.msg,
icon: 'none',
})
Taro.hideLoading()
}
}
else if (res.cancel) {
console.log('用户点击取消')
}
},
})
}
// 数组去重
const filterArr = (arr) => {
const newArr: any[] = []
// 控制外循环
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] == arr[j]) {
arr[j] = 0
}
}
// 去除值为0的
if (arr[i] == 0) {
continue
}
else {
// 放入新的数组
newArr.push(arr[i])
}
}
return newArr
}
// 计算预估金额
const totalMoney = useMemo(() => {
const arr: any = []
goodList.forEach((item) => {
item.product_colors.forEach((it) => {
arr.push(Number(it.total_sale_price))
})
})
const hate = sum(arr)
return hate
}, [goodList])
// 计算总面料
const totalProduct = useMemo(() => {
const arr: any = []
goodList.forEach((item) => {
arr.push(item)
})
return arr.length
}, [goodList])
// 计算总颜色
const totalColors = useMemo(() => {
const arr: any = []
goodList.forEach((item) => {
item.product_colors.forEach((it) => {
arr.push(it)
})
})
return arr.length
}, [goodList])
// 计算总颜色数量
const totalColorsNums = useMemo(() => {
const arr: any = []
goodList.forEach((item) => {
item.product_colors.forEach((it) => {
arr.push(Number(it.nums))
})
})
const hate = sum(arr)
return hate
}, [goodList])
function sum(arr) {
let s = 0
for (let i = arr.length - 1; i >= 0; i--) {
s += arr[i]
}
return s
}
return (
<View className={styles.mainBox}>
<AddressDetailBox
showBtn={showBtn}
showWhatFont={showWhatFont}
navSelect={obj => handSelect(obj)}
obj={infoObj}
receivingStatus={receivingStatus}
onReceivingStatus={(e, value) => onReceivingStatus(e, value)}
></AddressDetailBox>
<DefaultBox
showMode
title="客户信息"
modeName={infoObj.sale_mode_name}
>
<View className={styles.pussBox}>
<View className={styles.pussName}>{infoObj.purchaser_name}</View>
<View className={styles.pussPhone}>{infoObj.purchaser_phone}</View>
</View>
</DefaultBox>
<View className={styles.addBtn} onClick={() => navTo()}></View>
<View className={styles.total}> {totalProduct} {totalColors} {totalColorsNums} {infoObj.sale_mode === 0 ? '条' : 'm'}</View>
<View className={styles.productBox}>
<GoodsItem
list={goodList}
obj={infoObj}
clickReduce={it => clickReduce(it)}
handPlus={it => handPlus(it)}
onBlur={(e, it) => onBlur(e, it)}
modeFont={infoObj?.sale_mode}
></GoodsItem>
<View className={styles.flexMoney}>
<View className={styles.flexTotalBox}>
<View className={styles.totalFont}>{payFont}</View>
</View>
<View className={styles.shoudPay}>¥{formatPriceDiv(totalMoney)}</View>
</View>
{/* <View className={styles.flexMoney}>
<View className={styles.flexTotalBox}>
<View className={styles.totalFont}>实付金额</View>
</View>
<View className={styles.shoudPay}>¥{formatPriceDiv(infoObj.actual_amount)}</View>
</View> */}
{
infoObj?.wait_pay_amount < 0 && <View className={styles.flexMoney}>
<View className={styles.flexTotalBox}>
<View className={styles.totalFont}>{infoObj?.wait_pay_amount?.toString().indexOf('-') !== -1 ? '退款金额' : '待付金额'}</View>
</View>
<View className={styles.shoudPay}>¥{formatPriceDiv(infoObj.wait_pay_amount)}</View>
</View>
}
{
infoObj?.wait_pay_amount > 0 && <View className={styles.flexMoney}>
<View className={styles.flexTotalBox}>
<View className={styles.totalFont}>{infoObj?.wait_pay_amount?.toString().indexOf('-') !== -1 ? '退款金额' : '待付金额'}</View>
</View>
<View className={styles.shoudPay}>¥{formatPriceDiv(infoObj.wait_pay_amount)}</View>
</View>
}
</View>
<DefaultBox title="订单信息">
{
orderMsg.map((item, index) => {
return (
<View className={styles.detailBox} key={index}>
<View className={styles.detailFont}>
{item.leftTitle}
</View>
<View className={styles.detailRightFlex}>
<View className={styles.detailRight}>{item.rightTitle}</View>
{item.showBtn && <View className={styles.detailBtn} onClick={() => clipboardData()}></View>}
</View>
</View>
)
})
}
</DefaultBox>
<DefaultBox title="备注信息" showMode modeName={showRemarkFont} clickNode={() => setShowDesc(showRemarkFont != '')}>
<View className={styles.remarkFont}>{infoObj.remark === '' ? '暂无' : infoObj.remark}</View>
</DefaultBox>
<Popup show={showDesc} title="填写/编辑备注" showTitle onClose={() => setShowDesc(false)}>
<View style={{ margin: '24rpx' }}>
<Remark
// onSave={(e) => getRemark(e)}
onChange={e => onChange(e)}
defaultValue={infoObj.remark}
/>
<View className={styles.order_save_address} onClick={() => getRemark()}></View>
</View>
</Popup>
<View className={styles.safeBottom}></View>
<View className={styles.bottomBox}>
<View className={styles.bottomBtn} onClick={() => handSubmit()}></View>
</View>
</View >
)
}
export default OrderDetails