✨ feat(购物页面): 购物页面UI完成度80%

This commit is contained in:
xuan
2022-09-15 20:01:04 +08:00
parent fee33aec38
commit b4663f8507
29 changed files with 501 additions and 206 deletions
@@ -5,7 +5,7 @@
justify-content: space-between;
background-color: white;
padding: 16px 24px;
.bottomLeft{
margin-left: 12px;
.moneyText{
@@ -0,0 +1,65 @@
.colorKindItem {
width: 100%;
height: 100%;
margin-left: 20px;
padding: 16px 0;
display: flex;
flex-flow: row nowrap;
align-items: center;
justify-content: space-between;
&__left {
flex: none;
width: 120px;
height: 120px;
border-radius: 8px;
margin-right: 24px;
&--image {
width: 100%;
height: 100%;
}
}
&__center {
display: flex;
flex-flow: column nowrap;
justify-content: space-between;
flex: 1 1 auto;
&--title {
color: $color_font_one;
font-size: 28px;
@include common_ellipsis(2);
}
&--detail {
}
&--ID {
color: rgba($color: #000000, $alpha: 0.4);
font-size: 24px;
@include common_ellipsis();
}
&--description {
color: rgba($color: #000000, $alpha: 0.4);
font-size: 24px;
@include common_ellipsis();
}
}
&__right {
flex: none;
display: flex;
flex-flow: column nowrap;
align-items: flex-end;
justify-content: space-around;
align-self: stretch;
&--price {
color: $color_money;
font-weight: 550;
font-size: 28px;
}
&--counter {
}
}
}
.checkbox{
padding: 0 24px;
}
.selected {
background-color: #F8FAFF;
}
@@ -0,0 +1,116 @@
import { View, Text, Image } from '@tarojs/components'
import MCheckbox from '@/components/checkbox'
import Counter from '@/components/counter'
import { FC, memo, ReactNode, useCallback, useEffect, useState } from 'react'
import classnames from 'classnames'
import styles from './index.module.scss'
import { debounce } from '@/common/util'
import { formatPriceDiv } from '@/common/format'
import { EnumSaleMode } from '@/common/Enumerate'
type PropsType = {
item: Record<string, any> & object
orderType: EnumSaleMode
isSelected: boolean
onChecked?: Function
onUnChecked?: Function
}
const selectList = [
{ value: 0, title: '大货', unit: '条', eunit: 'kg', step: 1, digits: 0, minNum: 1, maxNum: 100000, defaultNum: 1 },
{ value: 1, title: '剪板', unit: '米', eunit: 'm', step: 1, digits: 2, minNum: 0.5, maxNum: 9.99, defaultNum: 1 },
{ value: 2, title: '散剪', unit: '米', eunit: 'kg', step: 1, digits: 2, minNum: 3, maxNum: 100000, defaultNum: 3 },
]
const ColorKindItem: FC<PropsType> = memo(
(props) => {
const { item, orderType = EnumSaleMode.Bulk, isSelected = false, onChecked, onUnChecked } = props
console.log('重新渲染', item.id, orderType)
//格式化金额
const formatPirce = useCallback((price) => {
return Number(formatPriceDiv(price))
}, [])
//格式化数量
const formatCount = useCallback((item) => {
return item.sale_mode == EnumSaleMode.Bulk ? item.roll : item.length / 100
}, [])
//格式化单位
const formatUnit = useCallback((item) => {
return item.sale_mode == EnumSaleMode.Bulk ? '条' : '米'
}, [])
// const [checked, setCheck] = useState(false)
// useEffect(() => {
// setCheck(isSelected)
// console.log('useEffect', isSelected)
// }, [isSelected])
const handleSelect = () => {
console.log('handleSelect')
// setCheck(true)
onChecked && onChecked({ ...item, checked: true })
}
const handleClose = () => {
// setCheck(false)
onUnChecked && onUnChecked({ ...item, checked: false })
}
const getInputValue = debounce(async (num, item) => {}, 300)
return (
<MCheckbox
triggerLabel={false}
status={isSelected}
onSelect={handleSelect}
onClose={handleClose}
customClassName={classnames(styles.checkbox, isSelected ? styles.selected : '')}
customTextClass={styles.colorKindItem}>
<View className={styles['colorKindItem__left']}>
<Image className={styles['colorKindItem__left--image']} mode='aspectFill' src='https://test.cdn.zzfzyc.com/mall/no_img.png'></Image>
</View>
<View className={styles['colorKindItem__center']}>
<Text className={styles['colorKindItem__center--title']}>001# 环保黑 环保黑 环保黑 环保黑 环保黑 环保黑</Text>
<View className={styles['colorKindItem__center--detail']}>
<Text className={styles['colorKindItem__center--ID']}>6002#220G</Text>
<Text className={styles['colorKindItem__center--description']}>流线棉拉架卫衣</Text>
</View>
</View>
<View className={styles['colorKindItem__right']}>
<View className={styles['colorKindItem__right--price']}>¥ 37.50/kg</View>
<View className={styles['colorKindItem__right--counter']}>
<Counter
onBlue={(e) => getInputValue(e, item)}
defaultNum={formatCount(item)}
step={selectList[orderType].step}
digits={selectList[orderType].digits}
onClickBtn={(e) => getInputValue(e, item)}
unit={formatUnit(item)}
minNum={selectList[orderType].minNum}
maxNum={selectList[orderType].maxNum}
/>
</View>
</View>
</MCheckbox>
)
},
(preProp, nextProp) => {
const stringifyPreProp = JSON.stringify(preProp.item)
const stringifyNextProp = JSON.stringify(nextProp.item)
console.log('memo==>', preProp, nextProp);
let needMemoized = true
if (preProp.isSelected !== nextProp.isSelected) {
needMemoized = false
}
if (preProp.orderType !== nextProp.orderType) {
needMemoized = false
}
if (stringifyPreProp !== stringifyNextProp) {
needMemoized = false
}
return needMemoized
},
)
export default ColorKindItem
@@ -1,8 +1,17 @@
.layout{
.layout {
margin: 24px;
padding-left: 0;
padding-right: 0;
.checkbox {
padding: 0 24px;
&--text {
width: 100%;
margin-left: 20px;
}
}
}
.line{
.line {
margin: 16px 0;
}
@@ -16,37 +25,40 @@
font-size: 32px;
font-family: $font_family;
font-weight: 550;
line-height: 2;
color: rgba($color: #000000, $alpha: 0.8);
margin-right: 16px;
}
// 汇总
.summary{
.summary {
color: rgba($color: #000000, $alpha: 0.4);
font-size: 24px;
}
}
.detailBox {
box-sizing: border-box;
overflow: hidden;
.orderType{
width: 100%;
.orderTitle {
padding: 0 24px;
display: flex;
align-items: center;
color: $color_font_one;
font-weight: 550;
font-size: 28px;
line-height: 2.5;
}
.orderType {
padding: 0 24px;
margin-left: 56px;
.orderTypeTitle{
color: $color_font_one;
font-weight: 550;
font-size: 28px;
line-height: 2.5;
}
.orderTypeDetail{
.orderTypeDetail {
display: flex;
gap: 0 16px;
}
}
.orderColor{
width: 100%;
.orderColor {
padding: 0 24px;
margin-left: 56px;
}
}
@@ -54,3 +66,20 @@
.bottomBox {
margin-top: 40px;
}
.drawerButton {
display: flex;
justify-content: center;
align-items: center;
Text {
font-size: 52px;
}
}
.drawerOpen{
height: auto;
}
.drawerClose {
height: 0;
}
@@ -9,36 +9,118 @@ import MCheckbox from '@/components/checkbox'
import Tag from '@/components/tag'
import Divider from '@/components/divider'
import NormalButton from '@/components/normalButton'
import ColorKindItem from '../colorKindItem'
import { EnumSaleMode } from '@/common/Enumerate'
type PropsType = {
obj?: any
}
const DrawerButton = memo<{ isOpen: boolean }>(({ isOpen }) => {
return isOpen ? <Text className='iconfont '></Text> : <Text className='iconfont '></Text>
return (
<View className={styles.drawerButton}>{isOpen ? <Text className='iconfont icon-shouqi'></Text> : <Text className='iconfont icon-zhankai'></Text>}</View>
)
})
export default memo((props: PropsType) => {
console.log('重新渲染 shoppingCartItem');
const [openDetail, setOpenDetail] = useState(false)
const handleOpenDetail = () => {
setOpenDetail((isOpen) => !isOpen)
}
const [selected, setSelect] = useState(0)
const [selected, setSelect] = useState<EnumSaleMode>(0)
const onSelectOrderType = (type) => {
const onSelectOrderType = (type: EnumSaleMode) => {
setSelect(type)
}
const [mockList, setMockList] = useState([
{
sale_mode: 0,
list: [
{ id: 0, sale_mode: 0, roll: 5, length: 0, checked: true },
{ id: 1, sale_mode: 0, roll: 6, length: 0, checked: false },
{ id: 2, sale_mode: 0, roll: 7, length: 0, checked: true },
],
},
{
sale_mode: 1,
list: [
{ id: 5, sale_mode: 1, roll: 0, length: 77700, checked: false },
{ id: 6, sale_mode: 1, roll: 0, length: 7600, checked: true },
{ id: 7, sale_mode: 1, roll: 0, length: 400, checked: true },
],
},
{
sale_mode: 2,
list: [
{ id: 8, sale_mode: 2, roll: 0, length: 11100, checked: false },
{ id: 9, sale_mode: 2, roll: 0, length: 8540, checked: true },
],
},
])
const handleChecked = (current) => {
console.log('handleChecked', current)
const index = mockList.findIndex(item=>item.sale_mode === selected)
const tempList = mockList[index].list.map((item) => {
if (item.id === current.id) {
item = current
}
return item
})
setMockList((pre=>{
return pre.map(item=>{
if(item.sale_mode === selected){
item.list = tempList
}
return item
})
}))
}
const handleUnChecked = (current) => {
const index = mockList.findIndex((item) => item.sale_mode === selected)
const tempList = mockList[index].list.map((item) => {
if (item.id === current.id) {
item = current
}
return item
})
setMockList((pre) => {
return pre.map((item) => {
if (item.sale_mode === selected) {
item.list = tempList
}
return item
})
})
}
const memoList = useMemo(() => {
return mockList[selected].list.map((item, index) => {
return (
<ColorKindItem
key={item.id}
isSelected={item.checked}
item={item}
orderType={selected}
onChecked={handleChecked}
onUnChecked={handleUnChecked}></ColorKindItem>
)
})
}, [mockList, selected])
return (
<LayoutBlock circle customClassName={styles.layout}>
<MCheckbox>
<MCheckbox customClassName={styles['checkbox']} customTextClass={styles['checkbox--text']} triggerLabel={false}>
<View className='flex-row justify-between' onClick={handleOpenDetail}>
<View className={styles.topItem}>
<View className='flex-row'>
<View className='flex-row items-center'>
<View className={styles.topTitle}>灵玉布行</View>
<Tag type='info' size='normal'>
<Tag type='info' size='normal' circle plain>
刘思伟
</Tag>
</View>
@@ -49,46 +131,47 @@ export default memo((props: PropsType) => {
<DrawerButton isOpen={openDetail} />
</View>
</MCheckbox>
<View className={styles.detailBox}>
<View className={classnames(styles.detailBox, openDetail ? styles.drawerOpen : styles.drawerClose)}>
<View className={styles.orderType}>
<Divider customClassName={styles.line}></Divider>
<View className={styles.orderTypeTitle}>订单类型</View>
<View className={styles.orderTitle}>订单类型</View>
<View className={styles.orderTypeDetail}>
<NormalButton
type={selected === 0 ? 'primary' : 'info'}
plain={selected !== 0}
type={selected === EnumSaleMode.Bulk ? 'primary' : 'info'}
plain={selected !== EnumSaleMode.Bulk}
customStyles={{ padding: '0 50rpx' }}
circle
onClick={() => onSelectOrderType(0)}>
onClick={() => onSelectOrderType(EnumSaleMode.Bulk)}>
大货
</NormalButton>
<NormalButton
type={selected === 1 ? 'primary' : 'info'}
plain={selected !== 1}
type={selected === EnumSaleMode.Plate ? 'primary' : 'info'}
plain={selected !== EnumSaleMode.Plate}
customStyles={{ padding: '0 50rpx' }}
circle
onClick={() => onSelectOrderType(1)}>
散剪
onClick={() => onSelectOrderType(EnumSaleMode.Plate)}>
剪板
</NormalButton>
<NormalButton
type={selected === 2 ? 'primary' : 'info'}
plain={selected !== 2}
type={selected === EnumSaleMode.BulkCut ? 'primary' : 'info'}
plain={selected !== EnumSaleMode.BulkCut}
customStyles={{ padding: '0 50rpx' }}
circle
onClick={() => onSelectOrderType(2)}>
剪板
onClick={() => onSelectOrderType(EnumSaleMode.BulkCut)}>
散剪
</NormalButton>
</View>
</View>
<View className={styles.orderColor}>
<Divider customClassName={styles.line}></Divider>
<View className={classnames(styles.orderTypeTitle, 'justify-between')}>
<View className={classnames(styles.orderTitle, 'justify-between')}>
<Text>布料颜色</Text>
<Tag type='danger' size='normal' circle>
<Tag type='danger' size='normal' circle plain={false}>
大货单位:条
</Tag>
</View>
</View>
<View className={styles.orderContainer}>{memoList}</View>
</View>
</LayoutBlock>
)
+1
View File
@@ -1,3 +1,4 @@
export default {
navigationBarTitleText: '购物页面',
}
+3 -1
View File
@@ -9,7 +9,9 @@
&--context {
justify-content: space-between;
height: 100%;
.shopping__list__container{
overflow: scroll;
}
}
}
.flexBox {
+2 -1
View File
@@ -52,7 +52,7 @@ const Shopping: FC = () => {
</Search>
</View>
<View className={classnames('flex-item', 'flex-col', styles['shopping--context'])}>
<View className={classnames('flex-item')}>
<View className={classnames(styles.shopping__list__container, 'flex-item')}>
{/* <InfiniteScroll
statusMore={statusMore}
selfonScrollToLower={getScrolltolower}
@@ -68,6 +68,7 @@ const Shopping: FC = () => {
})}
</InfiniteScroll> */}
<ItemList></ItemList>
<ItemList></ItemList>
</View>
{isManage ? (
<BottomEditBar onDelete={handleDelete} onSelectCheckbox={handleSelectAllCheckbox}></BottomEditBar>