feat:ID1000941): 调价及审批功能

This commit is contained in:
xuan 2023-03-17 16:53:14 +08:00
parent e2d28f5e80
commit 7d7f7eefa7
14 changed files with 722 additions and 247 deletions

View File

@ -1,5 +1,5 @@
{
"symbol_url": "http://at.alicdn.com/t/c/font_3619513_at0bezg87xk.js",
"symbol_url": "http://at.alicdn.com/t/c/font_3619513_bvm50rcxi49.js",
"parse_local_svg": true,
"local_svg_dir": "./src/styles/svg",
"save_dir": "./src/components/iconfont",

View File

@ -107,6 +107,27 @@
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "",
"pathName": "pages/submitOrder/index",
"query": "purchaser_id=1860&sale_mode=2&shopping_cart_product_color_list=%5B75384%2C75385%5D&purchaser_name=%E5%A4%A7%E5%90%89%E5%A4%A7%E5%88%A9",
"launchMode": "default",
"scene": null
},
{
"name": "",
"pathName": "pages/submitOrder/index",
"query": "purchaser_id=1808&sale_mode=0&shopping_cart_product_color_list=%5B71143%2C71159%2C71160%5D&purchaser_name=%E6%B8%B8%E5%AE%A2_65d59b5",
"launchMode": "default",
"scene": null
},
{
"name": "",
"pathName": "pages/orderDetails/index",
"query": "id=34311",
"launchMode": "default",
"scene": null
}
]
}

View File

@ -232,3 +232,19 @@ export const MpsaleOrdersubmit = () => {
method: 'put',
})
}
// 通过调价销售单审核
export const PassAdjustPriceAudit = () => {
return useRequest({
url: '/v2/mp/saleOrder/passAdjustPriceAudit',
method: 'put',
})
}
// 拒绝调价销售单审核
export const RefuseAdjustPriceAudit = () => {
return useRequest({
url: '/v2/mp/saleOrder/refuseAdjustPriceAudit',
method: 'put',
})
}

View File

@ -10,10 +10,11 @@ interface PropsType {
onClose?: (show: boolean) => void
onChange?: (isShow) => void
children?: React.ReactNode
zIndex?: number
}
// 弹出框
const Dialog = (props: PropsType) => {
const { showOverLay = true, show = false, onClose: _onClose, onChange: _onChange, children } = props
const { showOverLay = true, zIndex = 99, show = false, onClose: _onClose, onChange: _onChange, children } = props
const [_show, setShow] = usePropsValue({
value: show,
@ -47,14 +48,18 @@ const Dialog = (props: PropsType) => {
}
}, [show])
return _show
? <View className={style.dialog}>
? <View className={style.dialog} style={{ zIndex }}>
{/* 遮罩层 start */}
<View
style={{ zIndex: zIndex + 1 }}
className={classnames(style.dialog_mask, { [style.dialog_mask_active]: animShow, [style['drawer_mask--hidden']]: !showOverLay })}
onClick={onClose}
></View>
{/* 遮罩层 end */}
<View className={classnames(style.dialog_content, { [style.dialog_content_active]: animShow })}>
<View
style={{ zIndex: zIndex + 2 }}
className={classnames(style.dialog_content, { [style.dialog_content_active]: animShow })}
>
{children}
</View>
</View>

View File

View File

View File

@ -24,7 +24,7 @@ function hex2rgb(hex) {
return "rgb(" + rgb.join(",") + ")";
}
export type IconNames = 'icon-xinzenganniu' | 'icon-jianshaoanniu' | 'icon-xuanzhongyanse' | 'icon-jianyang' | 'icon-huozhuziti' | 'icon-a-0tianzhangqi' | 'icon-shangchuanwenli' | 'icon-gouwuche' | 'icon-zixun' | 'icon-dianhua' | 'icon-peibu' | 'icon-zhankai1' | 'icon-shouqi1' | 'icon-shouhou1' | 'icon-cangku1' | 'icon-saoma' | 'icon-dizhi1' | 'icon-huodaofukuan' | 'icon-yufukuan1' | 'icon-yue' | 'icon-zidingyi' | 'icon-jinetiaozheng' | 'icon-tuikuan1' | 'icon-zhankai' | 'icon-shouqi' | 'icon-lujing' | 'icon-jizhumima' | 'icon-a-jizhumima' | 'icon-weixindenglu' | 'icon-kehuxinxi' | 'icon-yewuyuanqizi' | 'icon-chakanquanbukehu' | 'icon-biyan' | 'icon-bianji' | 'icon-daikuan' | 'icon-cangku' | 'icon-guanlidingdan' | 'icon-mima' | 'icon-guanbi' | 'icon-jianshao' | 'icon-dingwei' | 'icon-saomiao' | 'icon-peihuo' | 'icon-shaixuan' | 'icon-paiming' | 'icon-shanchusousuoxinxi' | 'icon-shijian' | 'icon-sousuo' | 'icon-shouhou' | 'icon-sousuofanhui' | 'icon-sousuoshanchu' | 'icon-tuikuan' | 'icon-tishi' | 'icon-xianxiahuizong' | 'icon-xinzeng' | 'icon-yonghuming' | 'icon-yanjing' | 'icon-yufukuan' | 'icon-wodekefu' | 'icon-dizhi' | 'icon-shouhouzhongxin' | 'icon-wodeshoucang' | 'icon-shoukuanliebiao' | 'icon-madanguanli' | 'icon-qusechazhao' | 'icon-pandiansaoma' | 'icon-yaoqingma' | 'icon-duizhang' | 'icon-tihuoliebiao' | 'icon-yangpinduibi' | 'icon-yansequyang' | 'icon-fahuoliebiao' | 'icon-yuncangkucun' | 'icon-xiaoshou' | 'icon-qianzhicangkucun' | 'icon-lingquseka' | 'icon-gouwu1' | 'icon-dingdan1' | 'icon-gerenzhongxin1' | 'icon-shouye1' | 'icon-gerenzhongxin' | 'icon-dingdan' | 'icon-shouye' | 'icon-gouwu' | 'icon-wpassword';
export type IconNames = 'icon-bianji1' | 'icon-daishenhe' | 'icon-shenhejujue' | 'icon-shenhetongguo' | 'icon-xinzenganniu' | 'icon-jianshaoanniu' | 'icon-xuanzhongyanse' | 'icon-jianyang' | 'icon-huozhuziti' | 'icon-a-0tianzhangqi' | 'icon-shangchuanwenli' | 'icon-gouwuche' | 'icon-zixun' | 'icon-dianhua' | 'icon-peibu' | 'icon-zhankai1' | 'icon-shouqi1' | 'icon-shouhou1' | 'icon-cangku1' | 'icon-saoma' | 'icon-dizhi1' | 'icon-huodaofukuan' | 'icon-yufukuan1' | 'icon-yue' | 'icon-zidingyi' | 'icon-jinetiaozheng' | 'icon-tuikuan1' | 'icon-zhankai' | 'icon-shouqi' | 'icon-lujing' | 'icon-jizhumima' | 'icon-a-jizhumima' | 'icon-weixindenglu' | 'icon-kehuxinxi' | 'icon-yewuyuanqizi' | 'icon-chakanquanbukehu' | 'icon-biyan' | 'icon-bianji' | 'icon-daikuan' | 'icon-cangku' | 'icon-guanlidingdan' | 'icon-mima' | 'icon-guanbi' | 'icon-jianshao' | 'icon-dingwei' | 'icon-saomiao' | 'icon-peihuo' | 'icon-shaixuan' | 'icon-paiming' | 'icon-shanchusousuoxinxi' | 'icon-shijian' | 'icon-sousuo' | 'icon-shouhou' | 'icon-sousuofanhui' | 'icon-sousuoshanchu' | 'icon-tuikuan' | 'icon-tishi' | 'icon-xianxiahuizong' | 'icon-xinzeng' | 'icon-yonghuming' | 'icon-yanjing' | 'icon-yufukuan' | 'icon-wodekefu' | 'icon-dizhi' | 'icon-shouhouzhongxin' | 'icon-wodeshoucang' | 'icon-shoukuanliebiao' | 'icon-madanguanli' | 'icon-qusechazhao' | 'icon-pandiansaoma' | 'icon-yaoqingma' | 'icon-duizhang' | 'icon-tihuoliebiao' | 'icon-yangpinduibi' | 'icon-yansequyang' | 'icon-fahuoliebiao' | 'icon-yuncangkucun' | 'icon-xiaoshou' | 'icon-qianzhicangkucun' | 'icon-lingquseka' | 'icon-gouwu1' | 'icon-dingdan1' | 'icon-gerenzhongxin1' | 'icon-shouye1' | 'icon-gerenzhongxin' | 'icon-dingdan' | 'icon-shouye' | 'icon-gouwu' | 'icon-wpassword';
type PropsType = {
name: IconNames;
@ -84,6 +84,18 @@ const IconFont:FC<PropsType> = ({
className={classnames(icon, customClassName)}
/>
)} */}
{/* icon-bianji1 */}
{ name === 'icon-bianji1' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M480 112a32 32 0 0 1 0 64H176v672h672V576a32 32 0 0 1 64 0v304a32 32 0 0 1-32 32h-736a32 32 0 0 1-32-32v-736a32 32 0 0 1 32-32H480z m454.624-22.624a32 32 0 0 1 1.888 43.2l-1.888 2.048-400 400a32 32 0 0 1-47.136-43.2l1.888-2.048 400-400a32 32 0 0 1 45.248 0z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(69,129,255)'}'/%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
{/* icon-daishenhe */}
{ name === 'icon-daishenhe' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M627.675429 73.142857a36.571429 36.571429 0 0 1 25.929142 10.788572l195.181715 196.205714A36.571429 36.571429 0 0 1 859.428571 305.92v176A300.306286 300.306286 0 0 0 704 438.857143C537.362286 438.857143 402.285714 573.933714 402.285714 740.571429c0 81.773714 32.548571 155.977143 85.376 210.285714H128a36.571429 36.571429 0 0 1-36.571429-36.571429V109.714286a36.571429 36.571429 0 0 1 36.571429-36.571429h499.675429z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(51,127,255)'}'/%3E%3Cpath d='M704 512C830.244571 512 932.571429 614.326857 932.571429 740.571429S830.244571 969.142857 704 969.142857 475.428571 866.816 475.428571 740.571429 577.755429 512 704 512z m-18.285714 118.582857a27.428571 27.428571 0 0 0-27.428572 27.428572V777.142857a27.428571 27.428571 0 0 0 27.428572 27.428572h116.242285a27.428571 27.428571 0 0 0 27.428572-27.428572l-0.128-2.633143A27.428571 27.428571 0 0 0 801.956571 749.714286H713.142857v-91.702857a27.428571 27.428571 0 0 0-27.428571-27.428572z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(51,127,255)'}' opacity='.4'/%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
{/* icon-shenhejujue */}
{ name === 'icon-shenhejujue' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M627.675429 73.142857a36.571429 36.571429 0 0 1 25.929142 10.788572l195.181715 196.205714A36.571429 36.571429 0 0 1 859.428571 305.92v176A300.306286 300.306286 0 0 0 704 438.857143C537.362286 438.857143 402.285714 573.933714 402.285714 740.571429c0 81.773714 32.548571 155.977143 85.376 210.285714H128a36.571429 36.571429 0 0 1-36.571429-36.571429V109.714286a36.571429 36.571429 0 0 1 36.571429-36.571429h499.675429z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(246,72,97)'}'/%3E%3Cpath d='M704 512C830.244571 512 932.571429 614.326857 932.571429 740.571429S830.244571 969.142857 704 969.142857 475.428571 866.816 475.428571 740.571429 577.755429 512 704 512z m92.891429 135.68a26.276571 26.276571 0 0 0-37.156572 0L704 703.433143l-55.734857-55.716572a26.276571 26.276571 0 0 0-37.138286 0l-1.700571 1.865143a26.276571 26.276571 0 0 0 1.700571 35.291429l55.716572 55.716571-55.716572 55.734857a26.276571 26.276571 0 0 0 37.138286 37.138286l55.734857-55.734857 55.734857 55.734857c10.24 10.258286 26.88 10.258286 37.138286 0l1.700571-1.865143a26.276571 26.276571 0 0 0-1.700571-35.291428L741.156571 740.571429l55.716572-55.734858a26.276571 26.276571 0 0 0 0-37.138285z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(246,72,97)'}' opacity='.4'/%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
{/* icon-shenhetongguo */}
{ name === 'icon-shenhetongguo' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M627.675429 73.142857a36.571429 36.571429 0 0 1 25.929142 10.788572l195.181715 196.205714A36.571429 36.571429 0 0 1 859.428571 305.92v176A300.306286 300.306286 0 0 0 704 438.857143C537.362286 438.857143 402.285714 573.933714 402.285714 740.571429c0 81.773714 32.548571 155.977143 85.376 210.285714H128a36.571429 36.571429 0 0 1-36.571429-36.571429V109.714286a36.571429 36.571429 0 0 1 36.571429-36.571429h499.675429z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(3,177,95)'}'/%3E%3Cpath d='M704 512C830.244571 512 932.571429 614.326857 932.571429 740.571429S830.244571 969.142857 704 969.142857 475.428571 866.816 475.428571 740.571429 577.755429 512 704 512z m114.468571 152.082286a27.428571 27.428571 0 0 0-38.710857 2.413714l-95.670857 108.324571-46.884571-45.056a27.428571 27.428571 0 0 0-38.016 39.552l67.529143 64.914286a27.428571 27.428571 0 0 0 39.552-1.645714l114.596571-129.792a27.428571 27.428571 0 0 0-2.395429-38.710857z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(3,177,95)'}' opacity='.4'/%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
{/* icon-xinzenganniu */}
{ name === 'icon-xinzenganniu' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M341.333 0h341.334Q1024 0 1024 341.333v341.334Q1024 1024 682.667 1024H341.333Q0 1024 0 682.667V341.333Q0 0 341.333 0z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(51,127,255)'}'/%3E%3Cpath d='M512 256a32 32 0 0 1 32 32l-0.021 192H736a32 32 0 0 1 0 64H543.979L544 736a32 32 0 0 1-64 0l-0.021-192H288a32 32 0 0 1 0-64h191.979L480 288a32 32 0 0 1 32-32z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(255,255,255)'}'/%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }

View File

@ -42,12 +42,19 @@ const CustomTabBar: FC = () => {
const setSelected = (id: TabBarIndexMap[number]['id']) => {
dispatch({ type: TabBarType.SET_SELECTED, data: { tabItem, selectedId: id } })
}
const handleSelectTabItem = debounce(async(id: TabBarIndexMap[number]['id']) => {
setSelected(id)
const handleSelectTabItem = async(id: TabBarIndexMap[number]['id']) => {
if (id === 3) {
await openSubscriptionMessage({ scenes: 1 })
}
if (id === 4) {
await openSubscriptionMessage({ scenes: 2 })
}
console.log(id, 'item')
jump(id)
}
const jump = debounce((id) => {
setSelected(id)
Taro.switchTab({ url: tabItem?.find(item => item.id === id)?.pagePath as string })
}, 300)

View File

@ -128,7 +128,7 @@
border-radius: 16px;
position: absolute;
width: 100px;
height: 61px;
height: 64px;
z-index: 1;
transition: all 0.3s ease-in-out;
}

View File

@ -1,6 +1,88 @@
page {
background: #f7f7f7;
}
.passBackground {
background: url('https://cdn.zzfzyc.com/orderDetail/pass_background.png');
background-size: contain;
background-repeat: no-repeat;
}
.refuseBackground {
background-image: url('https://cdn.zzfzyc.com/orderDetail/refuse_background.png');
background-size: contain;
background-repeat: no-repeat;
}
.pendingBackground {
background: url('https://cdn.zzfzyc.com/orderDetail/pending_background.png');
background-size: contain;
background-repeat: no-repeat;
}
.status {
position: absolute;
top: 0;
left: 0;
width: 100%;
display: flex;
flex-flow: row nowrap;
box-sizing: border-box;
padding: 40px 32px;
height: 257px;
.statusLeft {
width: 50%;
}
.statusRight {
width: 50%;
font-size: 26px;
color: #736d6e;
line-height: 32px;
.name {
margin-top: 24px;
}
.time {
margin-top: 17px;
}
.buttonBar {
margin-top: 24px;
justify-content: flex-end;
display: flex;
flex-flow: row nowrap;
align-items: center;
}
.refuseButton {
border-radius: 8px;
background-color: #eff4fe;
}
.passButton {
border-radius: 8px;
margin-left: 20px;
}
}
.statusTitle {
display: flex;
flex-flow: row nowrap;
align-items: center;
.statusName {
margin-left: 10px;
font-size: 40px;
}
.refuseName{
color: #f65269;
}
.passName{
color: #00ab5b;
}
.pendingName{
color: #333;
}
}
.price {
color: #757172;
font-size: 26px;
margin-top: 16px;
}
}
.mainBox {
.pussBox {

View File

@ -1,4 +1,4 @@
import { View } from '@tarojs/components'
import { Text, 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'
@ -27,14 +27,18 @@ import {
OrderPaymentOrderPaymentSubmission,
OrderPaymentPreCollectOrderOrderPaymentMethodInfo,
OrderPaymentPreCollectOrderOrderPaymentSubmission,
PassAdjustPriceAudit,
RefuseAdjustPriceAudit,
} from '@/api/order'
import { alert, goLink } from '@/common/common'
import { formatDateTime, formatHashTag, formatPriceDiv, formatRemoveHashTag, formatWeightDiv } from '@/common/format'
import { formatDateTime, formatHashTag, formatMeterDiv, formatPriceDiv, formatRemoveHashTag, formatWeightDiv } from '@/common/format'
import IconFont from '@/components/iconfont/iconfont'
import { IMG_CND_Prefix, PAY_H5_CODE_URL } from '@/common/constant'
import SaleCodeList from '@/components/SaleCodeList'
import LabAndImg from '@/components/LabAndImg'
import Tag from '@/components/tag'
import { EnumSaleMode } from '@/common/Enumerate'
import NormalButton from '@/components/normalButton'
// 卡片盒子元素
interface Obs {
@ -121,13 +125,13 @@ const GoodsItem = (porps: PropGoods) => {
// {/* 第二个版本的样式 */}
<View className={styles.product_goods} key={inx}>
<View className={styles.prodct_name}>{formatHashTag(it.code, it.name)} x{obj?.sale_mode === 0 ? it.roll : it.length / 100}{obj?.sale_mode === 0 ? '条' : 'm'}</View>
<View className={styles.prodct_name}>{formatHashTag(it.code, it.name)} x{obj?.sale_mode === EnumSaleMode.Bulk ? it.roll : formatMeterDiv(it.length)}{obj?.sale_mode === EnumSaleMode.Bulk ? '条' : 'm'}</View>
<View className={styles.product_right}>
{
obj?.sale_mode === 0 && it?.sale_price !== it?.standard_sale_price && <View className={styles.lastBox}>¥{it?.standard_sale_price / 100}/{obj?.sale_mode === 1 ? 'm' : 'kg'}</View>
(obj?.sale_mode === EnumSaleMode.Bulk && it?.sale_price !== it?.standard_sale_price) ? <View className={styles.lastBox}>¥{formatPriceDiv(it?.standard_sale_price)}/kg</View> : null
}
<View className={styles.itemMoney}>¥{formatPriceDiv(it.sale_price)}/{obj?.sale_mode === 1 ? 'm' : 'kg'}</View>
<View className={styles.itemMoney}>¥{formatPriceDiv(it.sale_price)}/{obj?.sale_mode === EnumSaleMode.Plate ? 'm' : 'kg'}</View>
<View className={styles.itemMoneyOne}>¥{formatPriceDiv(it.total_sale_price)}</View>
</View>
</View>
@ -144,6 +148,96 @@ const GoodsItem = (porps: PropGoods) => {
)
}
const GoodsItemWithMemo = memo(GoodsItem)
enum AdjustPriceAuditStatus {
NONE = 0,
PASS = 3,
PENDING = 1,
REFUSE = 2,
}
interface NotificationProps{
salesOrderId: number
auditStatus: AdjustPriceAuditStatus
baseData: any
onSuccess: () => void
}
// 服务通知
const ServicesNotification = (props: NotificationProps) => {
const { salesOrderId, auditStatus, baseData, onSuccess } = props
const { fetchData: pass } = PassAdjustPriceAudit()
const { fetchData: refuse } = RefuseAdjustPriceAudit()
const handleRefuse = async() => {
const res = await refuse({
sale_order_id: salesOrderId,
})
if (res.success) {
Taro.showToast({
title: '拒绝成功',
icon: 'success',
duration: 2000,
})
onSuccess()
}
}
const handlePass = async() => {
const res = await pass({
sale_order_id: salesOrderId,
})
if (res.success) {
Taro.showToast({
title: '审核通过',
icon: 'success',
duration: 2000,
})
onSuccess()
}
}
const statusStyles = useMemo(() => {
const res = {
background: '',
textColor: '',
icon: null as React.ReactNode,
}
if (auditStatus === AdjustPriceAuditStatus.PENDING) {
res.background = styles.pendingBackground
res.textColor = styles.pendingName
res.icon = <IconFont name="icon-daishenhe" size={56} color="#337fff"></IconFont>
}
else if (auditStatus === AdjustPriceAuditStatus.PASS) {
res.background = styles.passBackground
res.textColor = styles.passName
res.icon = <IconFont name="icon-shenhetongguo" size={56} color="#03b15f"></IconFont>
}
else if (auditStatus === AdjustPriceAuditStatus.REFUSE) {
res.background = styles.refuseBackground
res.textColor = styles.refuseName
res.icon = <IconFont name="icon-shenhejujue" size={56} color="#f64861"></IconFont>
}
return res
}, [auditStatus])
return <View className={classnames(styles.status, statusStyles.background)}>
<View className={styles.statusLeft}>
<View className={styles.statusTitle}>
{statusStyles.icon}
<Text className={classnames(styles.statusName, statusStyles.textColor)}>{baseData.adjust_price_audit_status_name}</Text>
</View>
<View className={styles.price}> {formatPriceDiv(baseData.max_adjust_price)} </View>
</View>
<View className={styles.statusRight}>
{
auditStatus === AdjustPriceAuditStatus.PENDING
? <View className={styles.buttonBar}>
<NormalButton customClassName={styles.refuseButton} type="primary" size="small" circle plain onClick={handleRefuse}></NormalButton>
<NormalButton customClassName={styles.passButton} type="primary" size="small" circle onClick={handlePass}></NormalButton>
</View>
: <>
<View className={styles.name}>{baseData.adjust_price_audit_name}</View>
<View className={styles.time}>{formatDateTime(baseData.adjust_price_audit_time)}</View>
</>
}
</View>
</View>
}
const OrderDetails = () => {
const router = useRouter()
@ -207,7 +301,7 @@ const OrderDetails = () => {
})
const res = await infoFetch({ id: router.params.id })
orderMsg.map((it) => {
orderMsg.forEach((it) => {
if (it.leftTitle === '订单编号:') {
it.rightTitle = res.data.order_no
}
@ -828,12 +922,21 @@ const OrderDetails = () => {
})
}
const onSuccess = () => {
getDetail()
}
return (
<View className={styles.mainBox}>
<View style={infoObj.adjust_price_audit_status !== AdjustPriceAuditStatus.NONE ? { position: 'relative', paddingTop: '75px' } : {}}>
{
infoObj.adjust_price_audit_status !== AdjustPriceAuditStatus.NONE && <ServicesNotification salesOrderId={infoObj.id} auditStatus={infoObj.adjust_price_audit_status} baseData={infoObj} onSuccess={onSuccess}></ServicesNotification>
}
{(infoObj?.status != 10 && <OrderState picUrl={infoObj?.picUrl} orderInfo={infoObj} />)}
{
infoObj.status === 10 && <AdvanceOrderState orderInfo={infoObj} onRefresh={() => refresh()} />
}
</View>
<AddressDetailBox
showBtn={showBtn}
showWhatFont={showWhatFont}

View File

@ -1,8 +1,18 @@
page {
background: #f7f7f7;
height: 100vh;
}
.mainBox {
height: 100%;
overflow: hidden;
display: flex;
flex-flow: column nowrap;
justify-content: space-between;
.content {
flex: 1 1 auto;
overflow-y: scroll;
}
.pussBox {
margin-top: 24px;
display: flex;
@ -35,18 +45,18 @@ page {
}
.productBox {
width: 702px;
background: #ffffff;
border-radius: 16px;
margin-left: 24px;
padding-bottom: 36px;
overflow: hidden;
.flexMoney {
display: flex;
margin-top: 32px;
margin: 0 24px;
padding-bottom: 24px;
background-color: white;
align-items: center;
justify-content: space-between;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
.flexTotalBox {
display: flex;
@ -77,12 +87,6 @@ page {
}
}
.defaltBox {
margin: 24px;
padding: 24px 32px 24px 24px;
background: #ffffff;
border-radius: 16px;
.titleBox {
width: 638px;
display: flex;
@ -111,19 +115,22 @@ page {
background: #000000;
opacity: 0.1;
}
}
.goodsBox {
margin-top: 24px;
overflow: hidden;
border-bottom: 8px solid #f7f7f7;
.goodsProduct {
font-size: 28px;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
font-weight: 500;
color: #000000;
margin-left: 32px;
.goodsTitle {
flex: 1 1 auto;
font-size: 28px;
@include common_ellipsis(2);
}
.goodsEditIcon {
flex-shrink: 0;
}
}
.goodsLine {
@ -136,22 +143,18 @@ page {
}
.itemGoods {
margin-top: 24px;
display: flex;
.itemPic {
margin-left: 32px;
margin-right: 42px;
width: 108px;
height: 108px;
// background: #322F2F;
border-radius: 8px;
}
.itemRight {
padding-bottom: 24px;
width: 495px;
border-bottom: 1px solid #f7f7f7;
.item_right_top {
margin-bottom: 41px;
@ -181,6 +184,7 @@ page {
.flexBox {
display: flex;
align-items: center;
.itemMoney {
font-size: 28px;
margin-right: 10px;
@ -206,11 +210,9 @@ page {
}
.itemGoods:last-child {
margin-top: 24px;
display: flex;
.itemPic {
margin-left: 32px;
margin-right: 42px;
width: 108px;
height: 108px;
@ -273,7 +275,6 @@ page {
}
}
}
}
.goodsBox:last-child {
border-bottom: none;
@ -291,7 +292,6 @@ page {
.detailRight {
font-size: 28px;
font-weight: 400;
color: #000000;
}
@ -303,7 +303,6 @@ page {
border-radius: 8px;
border: 1px solid #337fff;
font-size: 24px;
font-weight: 400;
color: #337fff;
text-align: center;
@ -322,25 +321,26 @@ page {
.remarkFont {
margin-top: 24px;
font-size: 28px;
font-weight: 400;
color: #000000;
}
.safeBottom {
height: 300px;
.layoutBlock {
margin-bottom: 0;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.bottomBox {
width: 750px;
width: 100%;
height: 160px;
background: #ffffff;
display: flex;
// padding-top: 16px;
position: fixed;
bottom: 0;
position: relative;
z-index: 99;
box-shadow: 6px 0px 12px 0px rgba(0, 0, 0, 0.16);
justify-content: space-between;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
.leftBottom {
margin-top: 22px;
@ -390,3 +390,69 @@ page {
margin-right: 24px;
}
}
.modal {
width: 80vw;
background-color: white;
border-radius: 16px;
overflow: hidden;
.modalTitle {
box-sizing: border-box;
width: 100%;
text-align: center;
padding: 32px 48px;
font-size: 32px;
color: #333333;
font-weight: 500;
}
.modalContainer {
padding: 0 40px;
padding-bottom: 44px;
.inputBar {
margin-bottom: 24px;
.input {
border-radius: 16px;
background-color: #f5f5f5;
font-size: 32px;
padding: 20px 0;
padding-left: 32px;
}
}
.tips {
font-size: 24px;
color: #747474;
}
}
.modalButton {
display: flex;
flex-flow: row nowrap;
justify-content: space-around;
font-size: 36px;
&--cancel {
width: 50%;
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
color: #333333;
font-weight: 500;
}
&--confirm {
width: 50%;
display: flex;
font-weight: 500;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
color: $color_main;
}
.disabled {
opacity: 0.5;
}
}
}
.errorMsg {
color: $color_danger;
font-size: 24px;
margin-top: 8px;
}

View File

@ -1,4 +1,4 @@
import { View } from '@tarojs/components'
import { Input, Text, 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'
@ -14,11 +14,16 @@ import {
MpSaleOrderPreview,
} from '@/api/order'
import { alert } from '@/common/common'
import { formatDateTime, formatMeterDiv, formatPriceDiv, formatRemoveHashTag, formatWeightDiv } from '@/common/format'
import { formatDateTime, formatMeterDiv, formatPriceDiv, formatPriceMul, formatRemoveHashTag, formatWeightDiv } from '@/common/format'
import IconFont from '@/components/iconfont/iconfont'
import { MpPurchaserAddressList } from '@/api/addressList'
import LabAndImg from '@/components/LabAndImg'
import { EnumSaleMode } from '@/common/Enumerate'
import Divider from '@/components/divider'
import LayoutBlock from '@/components/layoutBlock'
import IconText from '@/components/iconText'
import Dialog from '@/components/Dialog'
import InputX from '@/components/InputX'
// 卡片盒子元素
interface Obs {
title?: string
@ -38,7 +43,7 @@ const DefaultBox = (props: Obs) => {
} = props
return (
<View className={styles.defaltBox}>
<LayoutBlock circle customStyle={{ marginTop: '24rpx' }}>
<View className={styles.titleBox}>
<View className={styles.title}>{title}</View>
{
@ -47,35 +52,128 @@ const DefaultBox = (props: Obs) => {
</View>
<View className={styles.modeLine}></View>
{children}
</View>
</LayoutBlock>
)
}
const DefaultBoxWithMemo = memo(DefaultBox)
// 产品商品元素
interface PropGoods {
// item?: {
// code?: string | number
// }
list: any[]
obj: {
sale_mode?: number | string
}
updateList: (list: any[]) => void
}
const GoodsItem = (porps: PropGoods) => {
const { list = [], obj = {} } = porps
const GoodsItem = (props: PropGoods) => {
const { list = [], obj = {}, updateList } = props
const [goodsList, setGoodsList] = useState(list)
useEffect(() => {
setGoodsList(list)
}, [list])
const labAndImgObj = useCallback((item) => {
return { lab: item.lab, rgb: item.rgb, texture_url: item.texture_url }
}, [])
// 长度为2 单价调整长度为1 批量调整
const editPayload = useRef<number[]>([])
// 批量调整
const handleClickBulkEdit = (parentId: number) => {
editPayload.current = [parentId]
setShowBulkPopup(true)
}
// 单价调整
const handleEdit = (subId: number, parentId: number) => {
editPayload.current = [subId, parentId]
setShowPopup(true)
}
const [showBulkPopup, setShowBulkPopup] = useState(false)
const handleBulkPopupChange = (bool) => {
setShowBulkPopup(bool)
}
const [showPopup, setShowPopup] = useState(false)
const handleChange = (bool) => {
setShowPopup(bool)
}
const handleCancel = () => {
setShowPopup(false)
setShowBulkPopup(false)
}
// 单价调整点击确认
const handleConfirm = () => {
if (errorMsg) { return }
const res = list.map((item) => {
if (item.id === editPayload.current[1]) {
item.product_colors = item.product_colors.map((it) => {
if (it.id === editPayload.current[0]) {
it.sale_price = it.origin_price + formatPriceMul(value)
}
return it
})
}
return item
})
setGoodsList(res)
handleCancel()
updateList(res)
}
// 批量调整点击确认
const handleBulkConfirm = () => {
if (errorMsg) { return }
const res = list.map((item) => {
if (item.id === editPayload.current[0]) {
item.product_colors = item.product_colors.map((it) => {
it.sale_price = it.origin_price + formatPriceMul(value)
return it
})
}
return item
})
setGoodsList(res)
handleCancel()
updateList(res)
}
// 批量调整
// 单价调整
const [value, setValue] = useState('-1.5')
const handleInput = (e) => {
const res = e.detail.value
setValue(res)
}
const errorMsg = useMemo(() => {
let msg = ''
if (Number(value) < -3) {
msg = '不能小于-3'
}
else {
msg = ''
}
return msg
}, [value])
return (
<>
<View>
{
list.map((item, index) => {
goodsList.map((item, index) => {
return (
<View className={styles.goodsBox} key={index}>
<View className={styles.goodsProduct}>{formatRemoveHashTag(item.code)}# {item.name}</View>
<View className={styles.goodsLine}></View>
<LayoutBlock circle key={index} customClassName={index === list.length - 1 ? styles.layoutBlock : ''}>
<View className={styles.goodsProduct}>
<View className={styles.goodsTitle}>{formatRemoveHashTag(item.code)}# {item.name}</View>
<View className={styles.goodsEditIcon} onClick={() => handleClickBulkEdit(item.id)}>
<IconText iconName="icon-bianji1" iconSize={30} svg color="#3d85ff" text="批量修改" textCustomStyle={{ color: '#3d85ff' }}></IconText>
</View>
</View>
<Divider direction="horizontal" customStyles={{ marginTop: '24rpx', marginBottom: '32rpx' }}></Divider>
{
item.product_colors.map((it, inx) => {
return (
@ -84,6 +182,7 @@ const GoodsItem = (porps: PropGoods) => {
<LabAndImg value={labAndImgObj(it)} />
</View>
<View className={styles.itemRight}>
<View>
<View className={styles.item_right_top}>
<View className={styles.itemName}>{formatRemoveHashTag(it.code)}# {it.name}</View>
<View className={styles.itemNums}>x{obj?.sale_mode === EnumSaleMode.Bulk ? it.roll : formatMeterDiv(it.length)}{obj?.sale_mode === 0 ? '条' : 'm'}</View>
@ -94,20 +193,60 @@ const GoodsItem = (porps: PropGoods) => {
{
(obj?.sale_mode === EnumSaleMode.Bulk && it?.sale_price !== it?.standard_price) ? <View className={styles.lastBox}>¥{formatPriceDiv(it?.standard_price)}/kg</View> : null
}
<View onClick={() => handleEdit(it.id, item.id)}>
<IconFont name="icon-bianji1" color="#3d85ff"></IconFont>
</View>
</View>
<View className={styles.itemMoneyOne}>¥{formatPriceDiv(it.estimate_amount)}</View>
</View>
</View>
<Divider direction="horizontal" customStyles={{ marginTop: '20rpx', marginBottom: '0' }}></Divider>
</View>
</View>
)
})
}
</View>
</LayoutBlock>
)
})
}
</>
<Dialog zIndex={999} show={showBulkPopup} onChange={handleBulkPopupChange}>
<View className={styles.modal}>
<View className={styles.modalTitle}></View>
<View className={styles.modalContainer}>
<View className={styles.inputBar}>
<InputX customInputClassName={styles.input} value={value} onInput={handleInput} placeholder="请输入调价价格"></InputX>
</View>
{errorMsg && <Text className={styles.errorMsg}>{errorMsg}</Text>}
<View className={styles.tips}></View>
</View>
<Divider direction="horizontal" customStyles={{ margin: '0', opacity: '0.7', transform: 'translateY(1px) scaleY(0.6)' }}></Divider>
<View className={styles.modalButton}>
<View className={styles['modalButton--cancel']} onClick={handleCancel}></View>
<Divider direction="vertical" customStyles={{ margin: '0', height: '100rpx', opacity: '0.7', transform: 'scaleX(0.6)' }}></Divider>
<View className={classnames(styles['modalButton--confirm'], errorMsg && styles.disabled)} onClick={handleBulkConfirm}></View>
</View>
</View>
</Dialog>
<Dialog zIndex={999} show={showPopup} onChange={handleChange}>
<View className={styles.modal}>
<View className={styles.modalTitle}></View>
<View className={styles.modalContainer}>
<View className={styles.inputBar}>
<InputX customInputClassName={styles.input} value={value} onInput={handleInput} placeholder="请输入调价价格"></InputX>
</View>
{errorMsg && <Text className={styles.errorMsg}>{errorMsg}</Text>}
<View className={styles.tips}></View>
</View>
<Divider direction="horizontal" customStyles={{ margin: '0', opacity: '0.7', transform: 'translateY(1px) scaleY(0.6)' }}></Divider>
<View className={styles.modalButton}>
<View className={styles['modalButton--cancel']} onClick={handleCancel}></View>
<Divider direction="vertical" customStyles={{ margin: '0', height: '100rpx', opacity: '0.7', transform: 'scaleX(0.6)' }}></Divider>
<View className={classnames(styles['modalButton--confirm'], errorMsg && styles.disabled)} onClick={handleConfirm}></View>
</View>
</View>
</Dialog>
</View>
)
}
@ -176,7 +315,17 @@ const SubmitOrder = () => {
shopping_cart_product_color_list: list,
}
const res = await infoFetch(query)
setInfoObj(res.data)
setInfoObj({
...res.data,
product_list: res.data.product_list.map((item) => {
item.product_colors = item.product_colors.map((it) => {
// 用于存储原始价格,(单价/批量)调整价格
it.origin_price = it.sale_price
return it
})
return item
}),
})
}
// 备注操作
@ -301,8 +450,18 @@ const SubmitOrder = () => {
getAddress()
getDetail()
}, [])
const updateList = (list: any[]) => {
setInfoObj(val => ({
...val,
product_list: list,
}))
}
return (
<View className={styles.mainBox}>
<View className={styles.content}>
<AddressDetailBox
navSelect={obj => handSelect(obj)}
obj={infoObj}
@ -316,28 +475,22 @@ const SubmitOrder = () => {
>
<View className={styles.pussBox}>
<View className={styles.pussName}>{pussName}</View>
{/* <View className={styles.pussPhone}>{infoObj.purchaser_phone}</View> */}
</View>
</DefaultBoxWithMemo>
{/* <View className={styles.total}> {infoObj.product_list?.length} 种面料,{infoObj.total_colors} 个颜色,共 {infoObj.sale_mode === 0 ? infoObj.total_number : infoObj.total_number / 100} {infoObj.sale_mode === 0 ? '条' : 'm'}</View> */}
<View className={styles.productBox}>
<GoodsItemWithMemo list={infoObj?.product_list} obj={infoObj}></GoodsItemWithMemo>
<GoodsItemWithMemo list={infoObj?.product_list} obj={infoObj} updateList={updateList}></GoodsItemWithMemo>
<View className={styles.flexMoney}>
<View className={styles.flexTotalBox}>
<View className={styles.totalFont}></View>
<IconFont name="icon-tishi" size={28} ></IconFont>
{/* <View className={classnames('iconfont', 'icon-tishi', styles.tishi)}></View> */}
</View>
<View className={styles.shoudPay}>¥{formatPriceDiv(infoObj.estimate_amount)}</View>
</View>
</View>
<DefaultBoxWithMemo title="备注信息" showMode modeName={`${'填写/修改备注'} >`} clickNode={() => setShowDesc(true)}>
<View className={styles.remarkFont}>{infoObj.remark === '' ? '暂无' : infoObj.remark}</View>
<View className={styles.remarkFont}>{!infoObj.remark ? '暂无' : infoObj.remark}</View>
</DefaultBoxWithMemo>
<Popup show={showDesc} showTitle={false} onClose={() => setShowDesc(false)}>
<Remark onSave={e => getRemark(e)} defaultValue={infoObj.remark} showInput={!!showDesc} />
</Popup>
<View className={styles.safeBottom}></View>
</View>
<View className={styles.bottomBox}>
<View className={styles.leftBottom}>
<View className={styles.topFlex}>
@ -348,6 +501,10 @@ const SubmitOrder = () => {
</View>
<View className={styles.rightBottom} onClick={() => handSure()}></View>
</View>
<Popup show={showDesc} showTitle={false} onClose={() => setShowDesc(false)}>
<Remark onSave={e => getRemark(e)} defaultValue={infoObj.remark} showInput={!!showDesc} />
</Popup>
</View>
)
}

View File

@ -77,8 +77,14 @@ export const UseSubscriptionMessage = () => {
if (res.success && res.data.TemplateID && res.data.TemplateID.length > 0) {
Taro.requestSubscribeMessage({
tmplIds: res.data.TemplateID,
success: (res) => {
console.log('success res', res)
Taro.showToast({
title: '订阅成功',
icon: 'success',
})
},
complete(res) {
console.log('qqqqqq')
resolve(res)
},
})