✨ feat:解决冲突
This commit is contained in:
commit
bd494b1759
1
global.d.ts
vendored
1
global.d.ts
vendored
@ -20,4 +20,5 @@ declare namespace NodeJS {
|
|||||||
declare const CURRENT_VERSION: string
|
declare const CURRENT_VERSION: string
|
||||||
declare const CURRENT_GITHASH: string
|
declare const CURRENT_GITHASH: string
|
||||||
declare const CURRENT_ENV: string
|
declare const CURRENT_ENV: string
|
||||||
|
declare const CURRENT_BASE_URL: string
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useRequest } from "@/use/useHttp"
|
import { useRequest } from '@/use/useHttp'
|
||||||
/**
|
/**
|
||||||
* 修改购物车
|
* 修改购物车
|
||||||
* @returns
|
* @returns
|
||||||
@ -13,19 +13,29 @@ export const ShoppingCartUpdateApi = () => {
|
|||||||
* 删除购物车商品
|
* 删除购物车商品
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const ShoppingCartDeleteApi = () => {
|
export const ShoppingCartDeleteApi = () => {
|
||||||
return useRequest({
|
return useRequest({
|
||||||
url: `/v2/mp/shoppingCart/productColor`,
|
url: `/v2/mp/shoppingCart/productColor`,
|
||||||
method: "delete",
|
method: 'delete',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 获取购物车商品列表
|
* 获取购物车商品列表
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const ShoppingCartListApi = () => {
|
export const ShoppingCartListApi = () => {
|
||||||
return useRequest({
|
return useRequest({
|
||||||
url: `/v2/mp/shoppingCart/productColor`,
|
url: `/v2/mp/shoppingCart/productColor`,
|
||||||
method: "get",
|
method: 'get',
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 调整购物车商品数量
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const AdjestShoppingCartApi = () => {
|
||||||
|
return useRequest({
|
||||||
|
url: `/v2/mp/shoppingCart/productColor/list`,
|
||||||
|
method: 'post',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,157 +1,141 @@
|
|||||||
.shopcartBox {
|
.shopcartBox {
|
||||||
padding-left: 32px;
|
padding: 0 32px;
|
||||||
|
|
||||||
.topTitle {
|
.topTitle {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
font-family: PingFangSC-Medium, PingFang SC;
|
font-weight: 500;
|
||||||
font-weight: 500;
|
color: #000000;
|
||||||
color: #000000;
|
margin-top: 24px;
|
||||||
margin-top: 24px;
|
margin-bottom: 8px;
|
||||||
margin-bottom: 8px;
|
}
|
||||||
|
|
||||||
|
.selectFont {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #000000;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
height: 1px;
|
||||||
|
background: #000000;
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.typeFont {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #000000;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexType {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
|
||||||
|
.activemodeFont {
|
||||||
|
margin-right: 16px;
|
||||||
|
width: 160px;
|
||||||
|
height: 68px;
|
||||||
|
background: rgba(51, 127, 255, 0.1);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #337fff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #337fff;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 68px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectFont {
|
.modeFont {
|
||||||
font-size: 24px;
|
margin-right: 16px;
|
||||||
font-family: PingFangSC-Regular, PingFang SC;
|
width: 160px;
|
||||||
font-weight: 400;
|
height: 68px;
|
||||||
color: #000000;
|
background: #e9e9e9;
|
||||||
margin-bottom: 24px;
|
border-radius: 8px;
|
||||||
|
opacity: 0.4;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #000000;
|
||||||
|
box-sizing: border-box;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 68px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flexFonts {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
.kingFont {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line {
|
.danwei {
|
||||||
margin-bottom: 24px;
|
margin-left: 16px;
|
||||||
// width: 686px;
|
width: 148px;
|
||||||
margin-right: 32px;
|
height: 30px;
|
||||||
height: 1px;
|
border-radius: 4px;
|
||||||
background: #000000;
|
border: 1px solid #e42945;
|
||||||
opacity: 0.1;
|
font-size: 22px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #e42945;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 30px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.typeFont {
|
.searchBox {
|
||||||
font-size: 28px;
|
margin-bottom: 32px;
|
||||||
font-family: PingFangSC-Medium, PingFang SC;
|
}
|
||||||
font-weight: 500;
|
|
||||||
color: #000000;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flexType {
|
.scrollviewBig {
|
||||||
display: flex;
|
.scrollview {
|
||||||
align-items: center;
|
// height: 300px;
|
||||||
margin-bottom: 32px;
|
|
||||||
|
|
||||||
.activemodeFont {
|
.kongBox {
|
||||||
margin-right: 16px;
|
height: 181px;
|
||||||
width: 160px;
|
|
||||||
height: 68px;
|
|
||||||
background: rgba(51, 127, 255, 0.1);
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid #337FFF;
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-size: 28px;
|
|
||||||
font-family: PingFangSC-Regular, PingFang SC;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #337FFF;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 68px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modeFont {
|
|
||||||
margin-right: 16px;
|
|
||||||
width: 160px;
|
|
||||||
height: 68px;
|
|
||||||
background: #E9E9E9;
|
|
||||||
border-radius: 8px;
|
|
||||||
opacity: 0.4;
|
|
||||||
font-size: 28px;
|
|
||||||
font-family: PingFangSC-Regular, PingFang SC;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #000000;
|
|
||||||
box-sizing: border-box;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 68px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.flexFonts {
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
align-items: center;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
|
|
||||||
.kingFont {
|
|
||||||
font-size: 28px;
|
|
||||||
font-family: PingFangSC-Medium, PingFang SC;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #000000;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.danwei {
|
|
||||||
margin-left: 16px;
|
|
||||||
width: 148px;
|
|
||||||
height: 30px;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1PX solid #E42945;
|
|
||||||
font-size: 22px;
|
|
||||||
font-family: PingFangSC-Medium, PingFang SC;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #E42945;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.searchBox {
|
|
||||||
// margin-left: 32px;
|
|
||||||
margin-right: 32px;
|
|
||||||
// width: 686px;
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scrollviewBig {
|
|
||||||
.scrollview {
|
|
||||||
// height: 300px;
|
|
||||||
|
|
||||||
.kongBox {
|
|
||||||
height: 181px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.kongOne {
|
|
||||||
height: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading_more {
|
|
||||||
height: 300px;
|
|
||||||
padding-bottom: 200px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.posBox {
|
.kongOne {
|
||||||
width: 100%;
|
height: 200px;
|
||||||
position: fixed;
|
}
|
||||||
z-index: 999;
|
|
||||||
bottom: calc($customTabBarHeight + env(safe-area-inset-bottom));
|
|
||||||
}
|
|
||||||
|
|
||||||
.noBottom {
|
.loading_more {
|
||||||
width: 100%;
|
height: 300px;
|
||||||
position: fixed;
|
padding-bottom: 200px;
|
||||||
z-index: 999;
|
display: flex;
|
||||||
bottom: env(safe-area-inset-bottom);
|
align-items: center;
|
||||||
}
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.posBox {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 999;
|
||||||
|
bottom: calc($customTabBarHeight + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
.noBottom {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 999;
|
||||||
|
bottom: env(safe-area-inset-bottom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrllStyle {
|
.scrllStyle {
|
||||||
height: 900px;
|
height: 75vh;
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ import Goods from "@/components/goodsItem"
|
|||||||
import BottomCustomer from "@/components/BottomCustomer"
|
import BottomCustomer from "@/components/BottomCustomer"
|
||||||
import VirtualList from '@tarojs/components/virtual-list'
|
import VirtualList from '@tarojs/components/virtual-list'
|
||||||
import DotLoading from "@/components/dotLoading"
|
import DotLoading from "@/components/dotLoading"
|
||||||
|
import Divider from '../divider';
|
||||||
interface prosObj {
|
interface prosObj {
|
||||||
showPopup?: false | true,
|
showPopup?: false | true,
|
||||||
closePopup?: () => void,
|
closePopup?: () => void,
|
||||||
@ -119,64 +120,89 @@ export default memo(forwardRef((props: prosObj, ref) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popup showTitle={false} show={showPopup} onClose={() => closePopup?.()}>
|
<Popup showTitle={false} show={showPopup} onClose={() => closePopup?.()}>
|
||||||
<ScrollView className={styles.scrllStyle} scrollY>
|
<ScrollView className={styles.scrllStyle} scrollY>
|
||||||
<View className={styles.shopcartBox}>
|
<View className={styles.shopcartBox}>
|
||||||
<View className={styles.topTitle}>{obj?.code}# {obj?.name}</View>
|
<View className={styles.topTitle}>
|
||||||
<View className={styles.selectFont}>已选 1 种面料,{selectTotal} 个颜色,共 {selectNums} {showModefont}</View>
|
{obj?.code}# {obj?.name}
|
||||||
<View className={styles.line}></View>
|
</View>
|
||||||
<View className={styles.typeFont}>布料类型</View>
|
<View className={styles.selectFont}>
|
||||||
<View className={styles.flexType}>
|
已选 1 种面料,{selectTotal} 个颜色,共 {selectNums} {showModefont}
|
||||||
{
|
</View>
|
||||||
typeList.map((item, index) => {
|
<Divider direction='horizontal' customStyles={{ margin: '12px 0' }}></Divider>
|
||||||
return (
|
<View className={styles.typeFont}>布料类型</View>
|
||||||
<View onClick={() => { handCheck?.(item) }} key={index} className={classnames(item.checked ? styles.activemodeFont : styles.modeFont)}>{item.name}</View>
|
<View className={styles.flexType}>
|
||||||
)
|
{typeList.map((item, index) => {
|
||||||
})
|
return (
|
||||||
}
|
<View
|
||||||
</View>
|
onClick={() => {
|
||||||
<View className={styles.line}></View>
|
handCheck?.(item)
|
||||||
<View className={styles.flexFonts}>
|
}}
|
||||||
<View className={styles.kingFont}>颜色分类({goodList?.length})</View>
|
key={index}
|
||||||
<View className={styles.danwei}>{modeFont == 0 ? '大货' : modeFont == 1 ? '剪版' : '散剪'}单位:{showModefont}</View>
|
className={classnames(item.checked ? styles.activemodeFont : styles.modeFont)}>
|
||||||
</View>
|
{item.name}
|
||||||
<View className={styles.searchBox}>
|
</View>
|
||||||
<Search cursorSpacing={100} placeholder='请输入搜索布料' showBtn={false} changeOnSearch={getSearchData} debounceTime={300} adjustPosition={true} />
|
)
|
||||||
</View>
|
})}
|
||||||
{
|
</View>
|
||||||
goodList.length > 0 && <>
|
<View style={{position: 'sticky', top: 0, background: 'white',zIndex: '9999'}}>
|
||||||
<View className={styles.scrollviewBig}>
|
<Divider direction='horizontal' customStyles={{ margin: '12px 0' }}></Divider>
|
||||||
<VirtualList
|
<View className={styles.flexFonts}>
|
||||||
className={styles.scrollview}
|
<View className={styles.kingFont}>颜色分类({goodList?.length})</View>
|
||||||
height={300} /* 列表的高度 */
|
<View className={styles.danwei}>
|
||||||
width='100%' /* 列表的宽度 */
|
{modeFont == 0 ? '大货' : modeFont == 1 ? '剪版' : '散剪'}单位:{showModefont}
|
||||||
itemData={goodList} /* 渲染列表的数据 */
|
</View>
|
||||||
itemCount={goodList.length + 0} /* 渲染列表的长度 */
|
</View>
|
||||||
itemSize={100} /* 列表单项的高度 */
|
<View className={styles.searchBox}>
|
||||||
overscanCount={1}>
|
<Search
|
||||||
{rows}
|
cursorSpacing={100}
|
||||||
</VirtualList>
|
placeholder='请输入搜索布料'
|
||||||
|
showBtn={false}
|
||||||
</View>
|
changeOnSearch={getSearchData}
|
||||||
|
debounceTime={300}
|
||||||
<View className={styles.kongOne}></View>
|
adjustPosition={true}
|
||||||
</>
|
/>
|
||||||
}
|
</View>
|
||||||
{
|
</View>
|
||||||
goodList.length === 0 && <>
|
{goodList.length > 0 && (
|
||||||
<View className={styles.loading_more}>加载中<DotLoading /></View>
|
<>
|
||||||
</>
|
<View className={styles.scrollviewBig}>
|
||||||
}
|
<VirtualList
|
||||||
{
|
className={styles.scrollview}
|
||||||
!hasBottom && <View style={{ height: '100rpx' }}></View>
|
height={300} /* 列表的高度 */
|
||||||
}
|
width='100%' /* 列表的宽度 */
|
||||||
<View className={classnames(hasBottom === true ? styles.posBox : styles.noBottom)}>
|
itemData={goodList} /* 渲染列表的数据 */
|
||||||
<BottomCustomer clientName={clientName} clientId={clientId} isDisabled={selectTotal > 0 && clientName !== '' ? false : true} handSure={() => { handSure() }}></BottomCustomer>
|
itemCount={goodList.length + 0} /* 渲染列表的长度 */
|
||||||
</View>
|
itemSize={100} /* 列表单项的高度 */
|
||||||
|
overscanCount={1}>
|
||||||
|
{rows}
|
||||||
|
</VirtualList>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
|
||||||
</Popup>
|
|
||||||
|
|
||||||
|
<View className={styles.kongOne}></View>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{goodList.length === 0 && (
|
||||||
|
<>
|
||||||
|
<View className={styles.loading_more}>
|
||||||
|
加载中
|
||||||
|
<DotLoading />
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{!hasBottom && <View style={{ height: '100rpx' }}></View>}
|
||||||
|
<View className={classnames(hasBottom === true ? styles.posBox : styles.noBottom)}>
|
||||||
|
<BottomCustomer
|
||||||
|
clientName={clientName}
|
||||||
|
clientId={clientId}
|
||||||
|
isDisabled={selectTotal > 0 && clientName !== '' ? false : true}
|
||||||
|
handSure={() => {
|
||||||
|
handSure()
|
||||||
|
}}></BottomCustomer>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</Popup>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 20px 20px 30px 20px;
|
padding: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ import { View } from '@tarojs/components'
|
|||||||
import Search from '@/components/search'
|
import Search from '@/components/search'
|
||||||
import SideBar from '@/components/sideBar'
|
import SideBar from '@/components/sideBar'
|
||||||
import Product from '@/components/product'
|
import Product from '@/components/product'
|
||||||
import MoveBtn from '@/components/moveBtn'
|
|
||||||
import ShopCart from '@/components/shoppingCart'
|
import ShopCart from '@/components/shoppingCart'
|
||||||
import { goLink } from '@/common/common'
|
import { goLink } from '@/common/common'
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
@ -13,7 +12,6 @@ import { mpproductcolorlist, mpshoppingCartproductColorlist } from "@/api/order"
|
|||||||
import { dataLoadingStatus } from '@/common/util'
|
import { dataLoadingStatus } from '@/common/util'
|
||||||
import Taro, { useDidShow } from '@tarojs/taro'
|
import Taro, { useDidShow } from '@tarojs/taro'
|
||||||
import { getFilterData } from '@/common/util'
|
import { getFilterData } from '@/common/util'
|
||||||
import userInfo from '@/reducers/userInfo'
|
|
||||||
import { ClientListApi } from '@/api/order'
|
import { ClientListApi } from '@/api/order'
|
||||||
export default () => {
|
export default () => {
|
||||||
|
|
||||||
@ -345,7 +343,7 @@ export default () => {
|
|||||||
<Product productList={productData.list} popupShow={(item) => showCart(item)} />
|
<Product productList={productData.list} popupShow={(item) => showCart(item)} />
|
||||||
</SideBar>
|
</SideBar>
|
||||||
</View>
|
</View>
|
||||||
<View className='common_safe_area_y'></View>
|
{/* <View className='common_safe_area_y'></View> */}
|
||||||
<ShopCart handSure={() => handSure()}
|
<ShopCart handSure={() => handSure()}
|
||||||
clientName={clientObj?.clientName}
|
clientName={clientObj?.clientName}
|
||||||
clientId={clientObj?.clientId}
|
clientId={clientObj?.clientId}
|
||||||
|
16
src/pages/shopping/README.md
Normal file
16
src/pages/shopping/README.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
购物页面的 组件结构
|
||||||
|
|
||||||
|
> Shopping
|
||||||
|
>
|
||||||
|
> > ShoppingProvider
|
||||||
|
> >
|
||||||
|
> > > ShoppingCartContainer
|
||||||
|
> > >
|
||||||
|
> > > > ShoppingCartItem
|
||||||
|
> > > >
|
||||||
|
> > > > > GoodsList
|
||||||
|
> > > > >
|
||||||
|
> > > > > > ColorKindItem
|
||||||
|
|
||||||
|
还用到发布订阅者模式 通知祖先组件请求接口更新数据
|
||||||
|
|
@ -8,18 +8,23 @@ import { debounce } from '@/common/util'
|
|||||||
import { formatImgUrl, formatPriceDiv } from '@/common/format'
|
import { formatImgUrl, formatPriceDiv } from '@/common/format'
|
||||||
import { EnumSaleMode } from '@/common/Enumerate'
|
import { EnumSaleMode } from '@/common/Enumerate'
|
||||||
import { selectList } from '../../config'
|
import { selectList } from '../../config'
|
||||||
|
import { AdjestShoppingCartApi } from '@/api/shopping/index'
|
||||||
import { Goods, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context'
|
import { Goods, ShoppingDispatchType, ShoppingStateContextValue, useShoppingDispatch, useShoppingState } from '../../context'
|
||||||
|
import { ShoppingStore } from '../../context/shoppingStore'
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
state?: Goods
|
state?: {
|
||||||
|
multipleSelection: Goods[]
|
||||||
|
Observer: ShoppingStore
|
||||||
|
}
|
||||||
purchaserId: number
|
purchaserId: number
|
||||||
itemData: Record<string, any> & object
|
itemData: Record<string, any> & object
|
||||||
orderType: EnumSaleMode
|
orderType: EnumSaleMode
|
||||||
}
|
}
|
||||||
|
|
||||||
let ColorKindItem: FC<PropsType> = props => {
|
let ColorKindItem: FC<PropsType> = props => {
|
||||||
console.log('Rerender component: ColorKindItem')
|
const { state, purchaserId, itemData, orderType = EnumSaleMode.Bulk } = props
|
||||||
const { state: multipleSelection, purchaserId, itemData, orderType = EnumSaleMode.Bulk } = props
|
console.log('Rerender component: ColorKindItem', itemData.id)
|
||||||
const dispatch = useShoppingDispatch()
|
const dispatch = useShoppingDispatch()
|
||||||
// console.log('checked==>', checked)
|
// console.log('checked==>', checked)
|
||||||
|
|
||||||
@ -43,12 +48,12 @@ let ColorKindItem: FC<PropsType> = props => {
|
|||||||
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
||||||
data: {
|
data: {
|
||||||
purchaserId: purchaserId,
|
purchaserId: purchaserId,
|
||||||
multipleSelection: { ...multipleSelection, [itemData.id]: itemData },
|
multipleSelection: { ...state?.multipleSelection, [itemData.id]: itemData },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
const temp = multipleSelection
|
const temp = state?.multipleSelection
|
||||||
delete temp?.[itemData.id]
|
delete temp?.[itemData.id]
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
||||||
@ -58,26 +63,39 @@ let ColorKindItem: FC<PropsType> = props => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const { fetchData } = AdjestShoppingCartApi()
|
||||||
|
|
||||||
|
// 调整条数/米数的接口 并在调整完成后重新请求整个购物车页面
|
||||||
// TODO:需要新增调整条数/米数的接口 并在调整完成后重新请求整个购物车页面
|
|
||||||
const getInputValue = debounce(async (num, itemData) => {
|
const getInputValue = debounce(async (num, itemData) => {
|
||||||
|
const targetColor: Record<string, any> = {
|
||||||
|
product_color_id: itemData.product_color_id,
|
||||||
|
roll: 0,
|
||||||
|
length: 0,
|
||||||
|
}
|
||||||
if (itemData.sale_mode === EnumSaleMode.Bulk) {
|
if (itemData.sale_mode === EnumSaleMode.Bulk) {
|
||||||
itemData.roll = num
|
itemData.roll = num
|
||||||
|
targetColor.roll = num
|
||||||
} else {
|
} else {
|
||||||
itemData.length = num
|
itemData.length = num
|
||||||
|
targetColor.length = num
|
||||||
}
|
}
|
||||||
|
const res = await fetchData({
|
||||||
}, 260)
|
color_list: [targetColor],
|
||||||
|
purchaser_id: purchaserId,
|
||||||
|
sale_mode: itemData.sale_mode,
|
||||||
|
sale_offset: itemData.sale_offset,
|
||||||
|
})
|
||||||
|
if (res.success) {
|
||||||
|
state?.Observer?.notify(purchaserId)
|
||||||
|
}
|
||||||
|
}, 400)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MCheckbox
|
<MCheckbox
|
||||||
status={multipleSelection?.hasOwnProperty(itemData.id) || false}
|
status={state?.multipleSelection?.hasOwnProperty(itemData.id) || false}
|
||||||
onSelect={handleSelect}
|
onSelect={handleSelect}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
customClassName={classnames(styles.checkbox, multipleSelection?.hasOwnProperty(itemData.id) ? styles.selected : '')}
|
customClassName={classnames(styles.checkbox, state?.multipleSelection?.hasOwnProperty(itemData.id) ? styles.selected : '')}
|
||||||
customTextClass={styles.colorKindItem}>
|
customTextClass={styles.colorKindItem}>
|
||||||
<View className={styles['colorKindItem__left']}>
|
<View className={styles['colorKindItem__left']}>
|
||||||
<Image className={styles['colorKindItem__left--image']} mode='aspectFill' src={formatImgUrl(itemData.product_color_texture_url)}></Image>
|
<Image className={styles['colorKindItem__left--image']} mode='aspectFill' src={formatImgUrl(itemData.product_color_texture_url)}></Image>
|
||||||
@ -101,8 +119,8 @@ let ColorKindItem: FC<PropsType> = props => {
|
|||||||
digits={selectList[orderType].digits}
|
digits={selectList[orderType].digits}
|
||||||
onClickBtn={e => getInputValue(e, itemData)}
|
onClickBtn={e => getInputValue(e, itemData)}
|
||||||
unit={formatUnit(itemData)}
|
unit={formatUnit(itemData)}
|
||||||
minNum={selectList[orderType].minNum}
|
minNum={itemData.min_num}
|
||||||
maxNum={selectList[orderType].maxNum}
|
maxNum={itemData.max_num}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@ -120,11 +138,11 @@ const withStateSlice = (comp, slice) => {
|
|||||||
return memo(forwardRef(Wrapper))
|
return memo(forwardRef(Wrapper))
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorKindItem = withStateSlice(
|
ColorKindItem = withStateSlice(ColorKindItem, (state: ShoppingStateContextValue, props: PropsType) => {
|
||||||
ColorKindItem,
|
return {
|
||||||
(state: ShoppingStateContextValue, props: PropsType) => {
|
multipleSelection: state.colorStore[props.purchaserId]['multipleSelection'],
|
||||||
return state.colorStore[props.purchaserId]['multipleSelection']
|
Observer: state.Observer,
|
||||||
},
|
}
|
||||||
)
|
})
|
||||||
|
|
||||||
export default ColorKindItem
|
export default ColorKindItem
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FC, ReactNode, useEffect, useReducer, useRef } from 'react'
|
import { FC, ReactNode, useEffect, useMemo, useReducer, useRef } from 'react'
|
||||||
import {
|
import {
|
||||||
ShoppingAction,
|
ShoppingAction,
|
||||||
ShoppingDispatchContext,
|
ShoppingDispatchContext,
|
||||||
@ -8,6 +8,7 @@ import {
|
|||||||
ShoppingStateContext,
|
ShoppingStateContext,
|
||||||
} from '../../context'
|
} from '../../context'
|
||||||
import { ColorStore, ShoppingStateContextValue } from '../../context'
|
import { ColorStore, ShoppingStateContextValue } from '../../context'
|
||||||
|
import { ShoppingStore } from '../../context/shoppingStore'
|
||||||
|
|
||||||
export type TriggerCheckboxOptions = {
|
export type TriggerCheckboxOptions = {
|
||||||
colorStore: ColorStore
|
colorStore: ColorStore
|
||||||
@ -15,15 +16,6 @@ export type TriggerCheckboxOptions = {
|
|||||||
setSelectedAmount: ShoppingDispatchContextValue['UPDATE_SELECTED_AMOUNT']
|
setSelectedAmount: ShoppingDispatchContextValue['UPDATE_SELECTED_AMOUNT']
|
||||||
}
|
}
|
||||||
|
|
||||||
type InitialState = {
|
|
||||||
colorStore: ColorStore
|
|
||||||
currentCheckedPurchaserId: number
|
|
||||||
currentCheckedSaleMode: number
|
|
||||||
isManageStatus: boolean
|
|
||||||
isMultipleSelection: boolean
|
|
||||||
selectedAmount: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ShoppingCartPropsType {
|
export interface ShoppingCartPropsType {
|
||||||
initialValues?: ColorStore
|
initialValues?: ColorStore
|
||||||
onTriggerCheckbox?: (options: TriggerCheckboxOptions) => void
|
onTriggerCheckbox?: (options: TriggerCheckboxOptions) => void
|
||||||
@ -35,18 +27,22 @@ export const ShoppingProvider: FC<ShoppingCartPropsType> = props => {
|
|||||||
|
|
||||||
const onTriggerCheckboxRef = useRef(onTriggerCheckbox)
|
const onTriggerCheckboxRef = useRef(onTriggerCheckbox)
|
||||||
onTriggerCheckboxRef.current = onTriggerCheckbox
|
onTriggerCheckboxRef.current = onTriggerCheckbox
|
||||||
|
// 发布订阅
|
||||||
|
const Observer = useMemo(() => new ShoppingStore(), [])
|
||||||
|
|
||||||
const [state, dispatch] = useReducer<(state: ShoppingStateContextValue, action: ShoppingAction) => InitialState>(shoppingReducer, {
|
const [state, dispatch] = useReducer<(state: ShoppingStateContextValue, action: ShoppingAction) => ShoppingStateContextValue>(shoppingReducer, {
|
||||||
colorStore: initialValues || {},
|
colorStore: initialValues || {},
|
||||||
currentCheckedPurchaserId: -1,
|
currentCheckedPurchaserId: -1,
|
||||||
currentCheckedSaleMode: 0,
|
currentCheckedSaleMode: 0,
|
||||||
isManageStatus: false,
|
isManageStatus: false,
|
||||||
isMultipleSelection: false,
|
isMultipleSelection: false,
|
||||||
selectedAmount: 0,
|
selectedAmount: 0,
|
||||||
|
Observer,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 这里要在 useEffect 也就是刷新 state 后再调用,否则如果在 onFieldsChangeRef 修改值会覆盖掉上次修改
|
// 这里要在 useEffect 也就是刷新 state 后再调用,否则如果在 onFieldsChangeRef 修改值会覆盖掉上次修改
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log('onTriggerCheckboxRef start run')
|
||||||
onTriggerCheckboxRef.current?.({
|
onTriggerCheckboxRef.current?.({
|
||||||
colorStore: state.colorStore,
|
colorStore: state.colorStore,
|
||||||
currentCheckedPurchaserId: state.currentCheckedPurchaserId,
|
currentCheckedPurchaserId: state.currentCheckedPurchaserId,
|
||||||
@ -54,6 +50,19 @@ export const ShoppingProvider: FC<ShoppingCartPropsType> = props => {
|
|||||||
})
|
})
|
||||||
}, [state.colorStore, state.currentCheckedPurchaserId])
|
}, [state.colorStore, state.currentCheckedPurchaserId])
|
||||||
|
|
||||||
|
// 加入一个监听,为 onFieldsChange 回调服务
|
||||||
|
// useEffect(() => {
|
||||||
|
// const unsubscribe = Observer.subscribe(() => {
|
||||||
|
// console.log('onTriggerCheckboxRef start run')
|
||||||
|
// onTriggerCheckboxRef.current?.({
|
||||||
|
// colorStore: state.colorStore,
|
||||||
|
// currentCheckedPurchaserId: state.currentCheckedPurchaserId,
|
||||||
|
// setSelectedAmount: amount => dispatch({ type: ShoppingDispatchType.UPDATE_SELECTED_AMOUNT, data: amount }),
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// return unsubscribe
|
||||||
|
// }, [Observer])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ShoppingStateContext.Provider value={state}>
|
<ShoppingStateContext.Provider value={state}>
|
||||||
<ShoppingDispatchContext.Provider value={dispatch}>{children}</ShoppingDispatchContext.Provider>
|
<ShoppingDispatchContext.Provider value={dispatch}>{children}</ShoppingDispatchContext.Provider>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Text, View } from '@tarojs/components'
|
import { Text, View } from '@tarojs/components'
|
||||||
import { FC, forwardRef, memo, useEffect, useMemo, useState, useTransition } from 'react'
|
import { FC, forwardRef, memo, useEffect, useMemo, useRef, useState, useTransition } from 'react'
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { formatMeterDiv } from '@/common/format'
|
import { formatMeterDiv } from '@/common/format'
|
||||||
@ -14,6 +14,8 @@ import IconFont from '@/components/iconfont/iconfont'
|
|||||||
import { isEmptyObject } from '@/common/common'
|
import { isEmptyObject } from '@/common/common'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import LoadingCard from '@/components/loadingCard'
|
import LoadingCard from '@/components/loadingCard'
|
||||||
|
import { ShoppingCartListApi } from '@/api'
|
||||||
|
import { ShoppingStore } from '../../context/shoppingStore'
|
||||||
|
|
||||||
interface ButtonPropsType {
|
interface ButtonPropsType {
|
||||||
isActive: boolean
|
isActive: boolean
|
||||||
@ -53,11 +55,13 @@ type PropsType = {
|
|||||||
state?: {
|
state?: {
|
||||||
multipleSelection?: GoodsMeta['multipleSelection']
|
multipleSelection?: GoodsMeta['multipleSelection']
|
||||||
currentCheckedPurchaserId?: number
|
currentCheckedPurchaserId?: number
|
||||||
|
Observer?: ShoppingStore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ShoppingCartItem: FC<PropsType> = props => {
|
let ShoppingCartItem: FC<PropsType> = props => {
|
||||||
const { itemData, state } = props
|
const { state } = props
|
||||||
|
const [itemData, setItemData] = useState(props.itemData)
|
||||||
const { multipleSelection, currentCheckedPurchaserId } = state!
|
const { multipleSelection, currentCheckedPurchaserId } = state!
|
||||||
const dispatch = useShoppingDispatch()
|
const dispatch = useShoppingDispatch()
|
||||||
|
|
||||||
@ -87,7 +91,10 @@ let ShoppingCartItem: FC<PropsType> = props => {
|
|||||||
}
|
}
|
||||||
dispatch({ type: ShoppingDispatchType.UPDATE_SELECTED_AMOUNT, data: 0 })
|
dispatch({ type: ShoppingDispatchType.UPDATE_SELECTED_AMOUNT, data: 0 })
|
||||||
dispatch({ type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_SALEMODE, data: selected })
|
dispatch({ type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_SALEMODE, data: selected })
|
||||||
dispatch({ type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_PURCHASERID, data: itemData?.purchaser_id as number })
|
dispatch({
|
||||||
|
type: ShoppingDispatchType.UPDATE_CURRENT_CHECKED_PURCHASERID,
|
||||||
|
data: itemData?.purchaser_id as number,
|
||||||
|
})
|
||||||
dispatch({ type: ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION, data: false })
|
dispatch({ type: ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION, data: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +138,58 @@ let ShoppingCartItem: FC<PropsType> = props => {
|
|||||||
}, [multipleSelection, currentCheckedPurchaserId, selected, itemData])
|
}, [multipleSelection, currentCheckedPurchaserId, selected, itemData])
|
||||||
|
|
||||||
const [isPending, startTransition] = useTransition()
|
const [isPending, startTransition] = useTransition()
|
||||||
|
const { fetchData } = ShoppingCartListApi()
|
||||||
|
|
||||||
|
// 发布订阅
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const unsubscribe = state?.Observer?.subscribe(async id => {
|
||||||
|
if (itemData?.purchaser_id !== id) return
|
||||||
|
console.log('request new data start run')
|
||||||
|
const res = await fetchData({
|
||||||
|
purchaser_id: id,
|
||||||
|
})
|
||||||
|
console.log('res===>', res)
|
||||||
|
if (res.success) {
|
||||||
|
const newGoodsKind = Object.fromEntries(
|
||||||
|
res.data[0]?.[BackEndSaleModeListFieldMap[selected]].map(item => [
|
||||||
|
item?.id,
|
||||||
|
{
|
||||||
|
id: item?.id,
|
||||||
|
estimate_amount: item.estimate_amount,
|
||||||
|
product_code: item.product_code,
|
||||||
|
product_color_code: item.product_color_code,
|
||||||
|
sale_mode: item.sale_mode,
|
||||||
|
count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
dispatch({
|
||||||
|
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
||||||
|
data: {
|
||||||
|
purchaserId: id,
|
||||||
|
goodsKind: newGoodsKind,
|
||||||
|
multipleSelection: Object.fromEntries(
|
||||||
|
Object.keys(multipleSelection!).map(id => [
|
||||||
|
id,
|
||||||
|
{
|
||||||
|
id,
|
||||||
|
estimate_amount: newGoodsKind[id].estimate_amount,
|
||||||
|
product_code: newGoodsKind[id].product_code,
|
||||||
|
product_color_code: newGoodsKind[id].product_color_code,
|
||||||
|
sale_mode: newGoodsKind[id].sale_mode,
|
||||||
|
count: selected === EnumSaleMode.Bulk ? newGoodsKind[id].roll : Number(formatMeterDiv(newGoodsKind[id].length)),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
setItemData(res.data[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 取消订阅
|
||||||
|
return unsubscribe
|
||||||
|
}, [multipleSelection])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutBlock
|
<LayoutBlock
|
||||||
@ -194,7 +253,13 @@ let ShoppingCartItem: FC<PropsType> = props => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View className={styles.orderContainer}>
|
<View className={styles.orderContainer}>
|
||||||
<GoodsList itemData={itemData} selected={selected} isPending={isPending} startTransition={startTransition} />
|
<GoodsList
|
||||||
|
multipleSelection={multipleSelection}
|
||||||
|
itemData={itemData}
|
||||||
|
selected={selected}
|
||||||
|
isPending={isPending}
|
||||||
|
startTransition={startTransition}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</>
|
</>
|
||||||
@ -205,52 +270,78 @@ let ShoppingCartItem: FC<PropsType> = props => {
|
|||||||
|
|
||||||
interface GoodsListPropType {
|
interface GoodsListPropType {
|
||||||
itemData?: ShoppingCartData
|
itemData?: ShoppingCartData
|
||||||
|
multipleSelection?: GoodsMeta['multipleSelection']
|
||||||
selected: EnumSaleMode
|
selected: EnumSaleMode
|
||||||
isPending: boolean
|
isPending: boolean
|
||||||
startTransition: React.TransitionStartFunction
|
startTransition: React.TransitionStartFunction
|
||||||
}
|
}
|
||||||
const GoodsList = memo<GoodsListPropType>(props => {
|
const GoodsList = memo<GoodsListPropType>(props => {
|
||||||
console.log('Rerender component: GoodsList')
|
console.log('Rerender component: GoodsList', props.multipleSelection)
|
||||||
const { itemData, selected, isPending, startTransition } = props
|
const { itemData, selected, isPending, startTransition, multipleSelection } = props
|
||||||
|
|
||||||
|
const currentSelected = useRef<EnumSaleMode | null>(null)
|
||||||
|
|
||||||
const dispatch = useShoppingDispatch()
|
const dispatch = useShoppingDispatch()
|
||||||
|
|
||||||
const [component, setComponent] = useState<JSX.Element | null>(null)
|
const [component, setComponent] = useState<JSX.Element | null>(null)
|
||||||
|
|
||||||
|
// 更新 GoodsList 组件
|
||||||
|
const updateComponent = () => {
|
||||||
|
setComponent(
|
||||||
|
itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? (
|
||||||
|
itemData?.[BackEndSaleModeListFieldMap[selected]].map(item => {
|
||||||
|
return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} itemData={item} orderType={selected}></ColorKindItem>
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<View className={styles.noList}>暂无数据</View>
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
startTransition(() => {
|
const newGoodsKind = Object.fromEntries(
|
||||||
setComponent(
|
itemData?.[BackEndSaleModeListFieldMap[selected]].map(item => [
|
||||||
itemData?.[BackEndSaleModeListFieldMap[selected]].length !== 0 ? (
|
item?.id,
|
||||||
itemData?.[BackEndSaleModeListFieldMap[selected]].map(item => {
|
{
|
||||||
dispatch({
|
id: item?.id,
|
||||||
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
estimate_amount: item.estimate_amount,
|
||||||
data: {
|
product_code: item.product_code,
|
||||||
purchaserId: itemData?.purchaser_id!,
|
product_color_code: item.product_color_code,
|
||||||
goodsKind: {
|
sale_mode: item.sale_mode,
|
||||||
[item?.id]: {
|
count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)),
|
||||||
id: item?.id,
|
},
|
||||||
estimate_amount: item.estimate_amount,
|
]),
|
||||||
product_code: item.product_code,
|
)
|
||||||
product_color_code: item.product_color_code,
|
// 这里做一层比较是为了 重新渲染的时候如果没有切换订单类型的话就不让面料的选中状态初始化
|
||||||
sale_mode: item.sale_mode,
|
if (currentSelected.current === selected) {
|
||||||
count: selected === EnumSaleMode.Bulk ? item.roll : Number(formatMeterDiv(item.length)),
|
dispatch({
|
||||||
},
|
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
||||||
},
|
data: {
|
||||||
multipleSelection: {},
|
purchaserId: itemData?.purchaser_id!,
|
||||||
},
|
goodsKind: newGoodsKind,
|
||||||
})
|
multipleSelection: multipleSelection,
|
||||||
return <ColorKindItem purchaserId={itemData.purchaser_id} key={item.id} itemData={item} orderType={selected}></ColorKindItem>
|
},
|
||||||
})
|
})
|
||||||
) : (
|
updateComponent()
|
||||||
<View className={styles.noList}>暂无数据</View>
|
} else {
|
||||||
),
|
// 重新把当前的选中状态赋值给ref 作为下一次比较的旧状态
|
||||||
)
|
currentSelected.current = selected
|
||||||
})
|
dispatch({
|
||||||
}, [itemData, selected])
|
type: ShoppingDispatchType.UPDATE_CHANGED_CHECKBOX,
|
||||||
|
data: {
|
||||||
|
purchaserId: itemData?.purchaser_id!,
|
||||||
|
goodsKind: newGoodsKind,
|
||||||
|
multipleSelection: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
startTransition(updateComponent)
|
||||||
|
}
|
||||||
|
}, [itemData, selected, multipleSelection])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isPending ? (
|
{isPending ? (
|
||||||
<View className='flex-row items-center justify-center' style={{ width: '100%', height: '200px' }}>
|
<View className={styles.noList} style={{margin: '60rpx 0'}}>
|
||||||
<LoadingCard />
|
<LoadingCard />
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
@ -262,12 +353,12 @@ const GoodsList = memo<GoodsListPropType>(props => {
|
|||||||
// State 分割组件 思路就是把 context 直接通过 props 的形式传给组件,这样的话就解决了 context 强制刷新 memo 的问题了
|
// State 分割组件 思路就是把 context 直接通过 props 的形式传给组件,这样的话就解决了 context 强制刷新 memo 的问题了
|
||||||
// 那么当 context 内的 value 被更新的时候,react 只会强制渲染 Wrapper
|
// 那么当 context 内的 value 被更新的时候,react 只会强制渲染 Wrapper
|
||||||
const withStateSlice = (comp, slice) => {
|
const withStateSlice = (comp, slice) => {
|
||||||
const MemoComp = memo(comp, (prevProps, nextProps)=>{
|
const MemoComp = memo(comp, (prevProps, nextProps) => {
|
||||||
let needMemo = true
|
let needMemo = true
|
||||||
if (JSON.stringify(prevProps.itemData) !== JSON.stringify(nextProps.itemData)) {
|
if (JSON.stringify(prevProps.itemData) !== JSON.stringify(nextProps.itemData)) {
|
||||||
needMemo = false
|
needMemo = false
|
||||||
}
|
}
|
||||||
if(JSON.stringify(prevProps.state) !== JSON.stringify(nextProps.state)){
|
if (JSON.stringify(prevProps.state) !== JSON.stringify(nextProps.state)) {
|
||||||
needMemo = false
|
needMemo = false
|
||||||
}
|
}
|
||||||
return needMemo
|
return needMemo
|
||||||
@ -283,6 +374,7 @@ const withStateSlice = (comp, slice) => {
|
|||||||
ShoppingCartItem = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({
|
ShoppingCartItem = withStateSlice(ShoppingCartItem, (state: ShoppingStateContextValue, props) => ({
|
||||||
multipleSelection: state.colorStore?.[props.itemData?.purchaser_id]?.['multipleSelection'],
|
multipleSelection: state.colorStore?.[props.itemData?.purchaser_id]?.['multipleSelection'],
|
||||||
currentCheckedPurchaserId: state.currentCheckedPurchaserId,
|
currentCheckedPurchaserId: state.currentCheckedPurchaserId,
|
||||||
|
Observer: state.Observer,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
export default ShoppingCartItem
|
export default ShoppingCartItem
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { EnumSaleMode } from '@/common/Enumerate'
|
import { EnumSaleMode } from '@/common/Enumerate'
|
||||||
import React, { Dispatch } from 'react'
|
import React, { Dispatch } from 'react'
|
||||||
import { useContext } from 'react'
|
import { useContext } from 'react'
|
||||||
|
import { ShoppingStore } from './shoppingStore'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 456: {
|
* 456: {
|
||||||
@ -8,7 +9,13 @@ import { useContext } from 'react'
|
|||||||
* colorKind: {
|
* colorKind: {
|
||||||
* 4562: {
|
* 4562: {
|
||||||
* id: 4562,
|
* id: 4562,
|
||||||
* checked: false
|
* ...
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* multipleSelection: {
|
||||||
|
* 4562: {
|
||||||
|
* id: 4562,
|
||||||
|
* ...
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* },
|
* },
|
||||||
@ -17,7 +24,7 @@ import { useContext } from 'react'
|
|||||||
* colorKind: {
|
* colorKind: {
|
||||||
* 4562: {
|
* 4562: {
|
||||||
* id: 4562,
|
* id: 4562,
|
||||||
* checked: false
|
* ...
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
@ -40,9 +47,7 @@ export interface GoodsMeta {
|
|||||||
goodsKind?: {
|
goodsKind?: {
|
||||||
[id: Goods['id']]: Goods
|
[id: Goods['id']]: Goods
|
||||||
}
|
}
|
||||||
multipleSelection: {
|
multipleSelection?: GoodsMeta['goodsKind']
|
||||||
[id: Goods['id']]: Goods
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShoppingStateContextValue {
|
export interface ShoppingStateContextValue {
|
||||||
@ -52,6 +57,7 @@ export interface ShoppingStateContextValue {
|
|||||||
currentCheckedSaleMode: EnumSaleMode
|
currentCheckedSaleMode: EnumSaleMode
|
||||||
colorStore: ColorStore
|
colorStore: ColorStore
|
||||||
selectedAmount: number
|
selectedAmount: number
|
||||||
|
Observer: ShoppingStore
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ShoppingDispatchType {
|
export enum ShoppingDispatchType {
|
||||||
@ -63,7 +69,7 @@ export enum ShoppingDispatchType {
|
|||||||
UPDATE_SELECTED_AMOUNT = 'UPDATE_SELECTED_AMOUNT',
|
UPDATE_SELECTED_AMOUNT = 'UPDATE_SELECTED_AMOUNT',
|
||||||
UPDATE_CHANGED_CHECKBOX = 'UPDATE_CHANGED_CHECKBOX',
|
UPDATE_CHANGED_CHECKBOX = 'UPDATE_CHANGED_CHECKBOX',
|
||||||
}
|
}
|
||||||
// UPDATE_MultipleSelection
|
|
||||||
export interface ShoppingDispatchContextValue {
|
export interface ShoppingDispatchContextValue {
|
||||||
[ShoppingDispatchType.UPDATE_MANAGE_STATUS]: (isManageStatus: ShoppingStateContextValue['isManageStatus']) => void
|
[ShoppingDispatchType.UPDATE_MANAGE_STATUS]: (isManageStatus: ShoppingStateContextValue['isManageStatus']) => void
|
||||||
[ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION]: (isMultipleSelection: ShoppingStateContextValue['isMultipleSelection']) => void
|
[ShoppingDispatchType.UPDATE_MULTIPLE_SELECTION]: (isMultipleSelection: ShoppingStateContextValue['isMultipleSelection']) => void
|
||||||
@ -109,7 +115,7 @@ export function shoppingReducer(state: ShoppingStateContextValue, action: Shoppi
|
|||||||
[data.purchaserId as number]: {
|
[data.purchaserId as number]: {
|
||||||
purchaserId: data.purchaserId,
|
purchaserId: data.purchaserId,
|
||||||
goodsKind: { ...state.colorStore[data.purchaserId]?.goodsKind, ...data.goodsKind },
|
goodsKind: { ...state.colorStore[data.purchaserId]?.goodsKind, ...data.goodsKind },
|
||||||
multipleSelection: { ...data.multipleSelection },
|
multipleSelection: data?.multipleSelection ? data.multipleSelection : state.colorStore[data.purchaserId]?.multipleSelection,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { GoodsMeta, ColorStore } from '.'
|
|
||||||
// 用于优化数据流 结合发布订阅 更新组件内部状态可以组件自己处理
|
// 用于优化数据流 结合发布订阅 更新组件内部状态可以组件自己处理
|
||||||
|
|
||||||
export type SubscribeCallback = (changedGoods: GoodsMeta) => void
|
import { ColorStore } from "."
|
||||||
|
|
||||||
|
export type SubscribeCallback = (changedGoods: any) => void
|
||||||
|
|
||||||
export class ShoppingStore {
|
export class ShoppingStore {
|
||||||
// 全局缓存
|
// 全局缓存
|
||||||
@ -9,7 +11,7 @@ export class ShoppingStore {
|
|||||||
// 监听器数组
|
// 监听器数组
|
||||||
private observers: SubscribeCallback[] = []
|
private observers: SubscribeCallback[] = []
|
||||||
|
|
||||||
constructor(initialValue: ColorStore) {
|
constructor(initialValue?: any) {
|
||||||
initialValue && this.updateStore(initialValue)
|
initialValue && this.updateStore(initialValue)
|
||||||
}
|
}
|
||||||
// 更新全局缓存
|
// 更新全局缓存
|
||||||
@ -27,9 +29,9 @@ export class ShoppingStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 通知
|
// 通知
|
||||||
notify(changedGoods: GoodsMeta) {
|
notify(changedGoods: any) {
|
||||||
// 循环调用
|
// 循环调用
|
||||||
this.observers.forEach((callback) => {
|
this.observers.forEach(callback => {
|
||||||
callback(changedGoods)
|
callback(changedGoods)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ export const Shopping: FC = memo(() => {
|
|||||||
// 计算总的预估金额
|
// 计算总的预估金额
|
||||||
const handleTriggerCheckbox = ({ colorStore, currentCheckedPurchaserId, setSelectedAmount }) => {
|
const handleTriggerCheckbox = ({ colorStore, currentCheckedPurchaserId, setSelectedAmount }) => {
|
||||||
const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.multipleSelection
|
const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.multipleSelection
|
||||||
console.log('handleTriggerCheckbox==>', colorStore)
|
console.log('handleTriggerCheckbox==>', multipleSelection)
|
||||||
|
|
||||||
if (multipleSelection) {
|
if (multipleSelection) {
|
||||||
const result = Object.values(multipleSelection).reduce((prev: number, value: Goods) => {
|
const result = Object.values(multipleSelection).reduce((prev: number, value: Goods) => {
|
||||||
@ -84,11 +84,18 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
|
|||||||
setSearchOptions(prev => ({ ...prev, short_name_or_phone: e }))
|
setSearchOptions(prev => ({ ...prev, short_name_or_phone: e }))
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const [shoppingCartData, setShoppingCartData] = useState<{ list: ShoppingCartData[]; total: number }>({ list: [], total: 0 })
|
const [shoppingCartData, setShoppingCartData] = useState<{
|
||||||
|
list: ShoppingCartData[]
|
||||||
|
total: number
|
||||||
|
}>({ list: [], total: 0 })
|
||||||
|
|
||||||
//数据加载状态
|
//数据加载状态
|
||||||
const statusMore = useMemo(() => {
|
const statusMore = useMemo(() => {
|
||||||
const status = dataLoadingStatus({ list: shoppingCartData.list, total: shoppingCartData.total, status: state.loading })
|
const status = dataLoadingStatus({
|
||||||
|
list: shoppingCartData.list,
|
||||||
|
total: shoppingCartData.total,
|
||||||
|
status: state.loading,
|
||||||
|
})
|
||||||
console.log('status==>', status)
|
console.log('status==>', status)
|
||||||
return status
|
return status
|
||||||
}, [shoppingCartData, state])
|
}, [shoppingCartData, state])
|
||||||
@ -144,7 +151,7 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
|
|||||||
// 批量某个客户的删除商品
|
// 批量某个客户的删除商品
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.['multipleSelection']
|
const multipleSelection = colorStore?.[currentCheckedPurchaserId]?.['multipleSelection']
|
||||||
let checked: Goods[] = Object.values(multipleSelection)
|
let checked: Goods[] = Object.values(multipleSelection!)
|
||||||
if (checked.length === 0) {
|
if (checked.length === 0) {
|
||||||
return Taro.showToast({ title: '请选择商品', icon: 'error' })
|
return Taro.showToast({ title: '请选择商品', icon: 'error' })
|
||||||
}
|
}
|
||||||
@ -203,6 +210,7 @@ const ShoppingCartContainer: FC<InternalContainer> = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={classnames('flex-col', styles.shopping)} id='shoppingContainer'>
|
<View className={classnames('flex-col', styles.shopping)} id='shoppingContainer'>
|
||||||
<View className={styles['shopping--topBar']} id='topBar'>
|
<View className={styles['shopping--topBar']} id='topBar'>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user