feat(领取色卡):

This commit is contained in:
czm 2023-02-16 20:22:26 +08:00
parent e043292f5d
commit 951acae9ba
32 changed files with 1041 additions and 185 deletions

34
src/api/colorCard.ts Normal file
View File

@ -0,0 +1,34 @@
import { useRequest as request } from '@/use/useHttp'
/**
*
* @returns
*/
export const GetColorCardApi = () => {
return request({
url: '/v1/mall/colorCardOrder/canAddCard',
method: 'post',
})
}
/**
*
* @returns
*/
export const SubmitColorCardApi = () => {
return request({
url: '/v1/mall/colorCardOrder/submit',
method: 'post',
})
}
/**
*
* @returns
*/
export const GetColorCardOrderApi = () => {
return request({
url: '/v1/mall/colorCardOrder/list',
method: 'get',
})
}

View File

@ -224,6 +224,11 @@ export default {
'index',
],
},
{
root: 'pages/colorCardOrderDetail',
pages: [
'index',
],
},
],
}

View File

@ -5,7 +5,7 @@ export const BASE_URL = CURRENT_BASE_URL
// export const BASE_URL = `http://192.168.0.89:40001/lymarket`
// export const BASE_URL = `http://192.168.1.165:40001/lymarket` // 王霞
// export const BASE_URL = 'https://test.zzfzyc.com/lymarket' // 测试环境
export const BASE_URL = 'https://pre.zzfzyc.com/lymarket' // 预发布
// export const BASE_URL = 'https://pre.zzfzyc.com/lymarket' // 预发布
// export const BASE_URL = `http://192.168.1.9:40001/lymarket` // 发
// export const BASE_URL = `http://192.168.1.9:50005/lymarket` // 发
// export const BASE_URL = `http://192.168.1.30:50001/lymarket` // 发
@ -14,7 +14,7 @@ export const BASE_URL = 'https://pre.zzfzyc.com/lymarket' // 预发布
// export const BASE_URL = `http://192.168.1.5:40001/lymarket` // 王霞
// export const BASE_URL = 'http://192.168.1.7:50002/lymarket' // 添
// export const BASE_URL = 'http://192.168.1.28:50001/lymarket' // 婷
// export const BASE_URL = 'http://192.168.1.42:50002/lymarket' // 杰
export const BASE_URL = 'http://192.168.1.42:50002/lymarket' // 杰
// CDN
// 生成密钥

View File

@ -36,14 +36,17 @@
border-color: $color_main;
}
}
.checkbox_main_no_selected {
border: 0 !important;
}
.checkbox_item {
display: flex;
align-items: center;
justify-content: center;
}
.no_checkbox_item {
border: 0;
background-color: #dddddd;
border: 0 !important;
background-color: #dddddd !important;
}
.checkbox_item_select {
background-color: $color_main;

View File

@ -68,16 +68,16 @@ const Checkbox = (props: params, ref) => {
[styles[`checkbox_main--${size}`]]: size,
[styles['checkbox_main--round']]: round,
[styles['checkbox_main--circle']]: circle,
[styles.checkbox_main_no_selected]: disabled,
}
return classObject
}
const getClassName = () => {
const classObject = {
return {
[styles.no_checkbox_item]: disabled,
[styles.checkbox_item_select]: selected,
}
return classObject
}
useImperativeHandle(ref, () => ({

View File

@ -13,6 +13,8 @@ interface params {
onChange?: (val: number) => void
onBlue?: (val: number) => void // 失去焦点触发
onClickBtn?: (val: number) => void
onMax?: () => void // 触发大于最大值回调
onMin?: () => void // 触发小于最小值回调
unit?: string
disabled?: true | false // 是否禁用
returnZero?: true | false // 少于最小值时是否归0
@ -28,6 +30,8 @@ const CounterDisplayName = (props: params) => {
onChange,
onBlue,
onClickBtn,
onMax,
onMin,
returnZero = false,
unit = '',
disabled = false,
@ -76,14 +80,14 @@ const CounterDisplayName = (props: params) => {
const count = value.count
let num_res = value.count
if (!isInteger(num_res)) {
console.log('num_resaa::', num_res)
num_res = Math.trunc(num_res)
}
else {
console.log('num_resbb::', num_res)
num_res = Big(count).minus(step).toNumber()
}
if (num_res < minNum) { onMin?.() }
if (returnZero) {
num_res = num_res < minNum ? 0 : num_res
}

View File

@ -0,0 +1,48 @@
.order_popup {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 0;
.order_popup_title {
color: $font_size_big;
font-weight: 700;
color: #000000;
padding-bottom: 20px;
}
.order_popup_input {
width: 100%;
padding: 0 25px;
box-sizing: border-box;
margin-top: 43px;
position: relative;
.descDataNum {
position: absolute;
right: 40px;
bottom: 10px;
height: 39px;
font-size: $font_size_medium;
color: $color_font_two;
}
textarea {
background-color: #f3f3f3;
border-radius: 10px;
width: 100%;
height: 313px;
padding: 20px;
padding-bottom: 50px;
box-sizing: border-box;
font-size: $font_size;
border: 2px solid #e6e6e6;
}
}
.order_save_address {
height: 82px;
background: $color_main;
border-radius: 40px;
width: 668px;
text-align: center;
line-height: 82px;
color: #fff;
margin-top: 60px;
}
}

View File

@ -0,0 +1,46 @@
import { Textarea, View } from '@tarojs/components'
import { useCallback, useEffect, useState } from 'react'
import styles from './index.module.scss'
import Popup from '@/components/popup'
interface Param {
onBlur?: (val: any) => void
onSave?: (val: string) => void
show: boolean
onClose: (val: boolean) => void
}
export default (props: Param) => {
const [descData, setDescData] = useState({
number: 0,
value: '',
count: 200,
})
const [showDesc, setShowDesc] = useState(false)
useEffect(() => {
setShowDesc(props.show)
}, [props.show])
const getDesc = useCallback((e) => {
const value = e.detail.value
let res = value
if (value.length > descData.count) {
res = value.slice(0, descData.count)
}
setDescData({ ...descData, number: res.length, value: res })
}, [])
const setSave = () => {
props.onSave?.(descData.value)
}
return (
<Popup show={showDesc} showTitle={false} onClose={() => props.onClose(false)}>
<View className={styles.order_popup}>
<View className={styles.order_popup_title}></View>
<View className={styles.order_popup_input}>
<Textarea value={descData.value} placeholder="请添加备注" maxlength={descData.count} cursorSpacing={100} onInput={e => getDesc(e)} onBlur={e => props.onBlur?.(e)}></Textarea>
<View className={styles.descDataNum}>{descData.number}/{descData.count}</View>
</View>
<View className={styles.order_save_address} onClick={() => setSave()}></View>
</View>
</Popup>
)
}

View File

@ -0,0 +1,15 @@
.order_address_list {
height: 80vh;
.order_address_title {
font-size: $font_size;
font-weight: 700;
width: 100%;
text-align: center;
padding: 20px 0 30px 0;
height: 100px;
}
.addressList_con {
padding-bottom: 20px;
height: calc(100% - 160px);
}
}

View File

@ -1,16 +1,28 @@
import { View } from '@tarojs/components'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import AddressList from '../AddressList'
import styles from './index.module.scss'
import Popup from '@/components/popup'
export default () => {
const [showAddressList, setShowAddressList] = useState(false)
return <Popup show={showAddressList} showTitle={false} onClose={() => setShowAddressList(false)}>
interface Params {
show: boolean
onClose: (val: boolean) => void
onSelect: (val: any) => void
}
export default (props: Params) => {
const [show, setShow] = useState(false)
useEffect(() => {
setShow(props.show)
}, [props.show])
const getSelect = (e) => {
props.onSelect(e)
props.onClose(false)
}
return <Popup show={show} showTitle={false} onClose={() => props.onClose(false)}>
<View className={styles.order_address_list}>
<View className={styles.order_address_title}></View>
<View className={styles.order_address_title}>2</View>
<View className={styles.addressList_con}>
<AddressList />
<AddressList onSelect={getSelect} />
</View>
</View>
</Popup>

View File

@ -1,12 +1,42 @@
import { Text, View } from '@tarojs/components'
import { useMemo } from 'react'
import styles from './index.module.scss'
import LabAndImg from '@/components/LabAndImg'
export default () => {
interface color_card_info {
count: number
lab: { l: number; a: number; b: number }
name: string
rgb: { r: number; g: number; b: number }
texture_url: string
}
export interface ParamItem {
color_card_count: number
color_card_number: number
id: number
order_id: number
order_no: string
order_status: number
order_status_name: string
shipment_mode: number
shipment_mode_name: string
color_card_info: color_card_info[]
}
interface Param {
value: ParamItem
}
export default (props: Param) => {
const { value } = props
const card_one = useMemo(() => {
return value.color_card_info ? value.color_card_info[0] : null
}, [value])
return <View className={styles.list_item}>
<View className={styles.item_header}>
<Text>XS-LY-2208220092</Text>
<Text></Text>
<Text>{value.order_no}</Text>
<Text>{value.order_status_name}</Text>
</View>
<View className={styles.item_con}>
<View className={styles.image}>
@ -15,16 +45,16 @@ export default () => {
<View className={styles.item_con_desc}>
<View className={styles.item_con_name}>
<Text>9265# 26S全棉双卫衣</Text>
<Text></Text>
<Text>{card_one?.name}</Text>
<Text>{value.shipment_mode_name}</Text>
</View>
<Text className={styles.item_con_count}>x1</Text>
<Text className={styles.item_con_count}>x{card_one?.count}</Text>
</View>
</View>
<View className={styles.card_info}>
<Text>:</Text>
<Text>3 3 </Text>
<Text>{value.color_card_count} {value.color_card_number} </Text>
</View>
<View className={styles.express}></View>
<View className={styles.btns}><Text></Text></View>

View File

@ -1,14 +1,17 @@
import { Image, Text, View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { useRef, useState } from 'react'
import { useEffect, useMemo, useRef, useState } from 'react'
import classNames from 'classnames'
import styles from './index.module.scss'
import type { ParamItem } from './components/productItem'
import ProductItem from './components/productItem'
import SelectList from '@/components/selectList'
import kong from '@/styles/image/kong.png'
import LabAndImg from '@/components/LabAndImg'
import InfiniteScroll from '@/components/infiniteScroll'
import { goLink } from '@/common/common'
import { GetColorCardOrderApi } from '@/api/colorCard'
import { dataLoadingStatus } from '@/common/util'
export default () => {
const [selectIndex, setSelectIndex] = useState(1)
@ -27,6 +30,41 @@ export default () => {
const changeStatus = (index: number) => {
setStatusIndex(index)
}
const [searchData, setSearchData] = useState<{ color_card_ids?: number[]; name?: string; page: number; size: number }>({
page: 1,
size: 10,
})
const [orderData, setOrderData] = useState<{ list: ParamItem[]; total: number }>({
list: [],
total: 0,
})
const { fetchData: fetchDataOrder, state: OrderState } = GetColorCardOrderApi()
const getColorCardOrder = async() => {
const res = await fetchDataOrder()
setOrderData(() => res.data)
}
useEffect(() => {
getColorCardOrder()
}, [])
// 上拉加载数据
const pageNum = useRef({ size: searchData.size, page: searchData.page })
const getScrolltolower = useCallback(() => {
if (colorCardData.list.length < colorCardData.total) {
pageNum.current.page++
const size = pageNum.current.size * pageNum.current.page
setSearchData(e => ({ ...e, size }))
}
}, [colorCardData])
// 数据加载状态
const statusMore = useMemo(() => {
return dataLoadingStatus({ list: orderData?.list, total: orderData?.total, status: OrderState.loading })
}, [orderData, OrderState])
return <View className={styles.main}>
<SelectList list={selectList} defaultIndex={selectIndex} onSelect={index => setSelectIndex(index)} />
<View className={styles.btn_list}>
@ -39,16 +77,16 @@ export default () => {
</View>}
<View className={styles.con_list}>
<InfiniteScroll
statusMore={2}
statusMore={statusMore}
refresherEnabled
// selfonScrollToLower={getScrolltolower}
// refresherTriggered={refresherTriggeredStatus}
// selfOnRefresherRefresh={getRefresherRefresh}
selfonScrollToLower={getScrolltolower}
refresherTriggered={refresherTriggeredStatus}
selfOnRefresherRefresh={getRefresherRefresh}
>
{new Array(10).fill('').map((item) => {
{orderData.list?.map((item) => {
return (
<View key={item.id} className={styles.order_item_con}>
<ProductItem />
<ProductItem value={item} />
</View>
)
})}

View File

@ -4,41 +4,43 @@ import styles from './index.module.scss'
import IconFont from '@/components/iconfont/iconfont'
import AddressList from '@/components/AddressList'
import Popup from '@/components/popup'
import SelectAddress from '@/components/selectAddress'
interface Param {
address_title: string
address_name: string
address_phone: string
address_mode: string
onSelect: (val: number) => void
}
export default (props: Param) => {
const {
address_title = '广东省佛山市禅城区南庄镇吉利大道872巷备份',
address_name = '谭先生',
address_phone = '13334726540',
address_mode = '物流',
} = props
const [data, setData] = useState({
address_title: '',
address_name: '',
address_phone: '',
address_mode: '物流',
})
const [showList, setShowList] = useState(true)
return <View className={styles.address_con}>
<IconFont name="icon-dizhiguanli" size={50} />
<View className={styles.message}>
<View className={styles.info_address}>
<View className={styles.address_name}>{address_title}</View>
<IconFont name="icon-rukou" color="#979797FF" />
</View>
<View className={styles.info_phone}>
<Text>{address_name + address_phone}</Text>
<Text>{address_mode}</Text>
</View>
</View>
<Popup show={showList} showTitle={false} onClose={() => setShowList(false)}>
<View className={styles.order_address_list}>
<View className={styles.order_address_title}></View>
<View className={styles.addressList_con}>
<AddressList />
const [showList, setShowList] = useState(false)
const getAddress = (e) => {
props.onSelect(e.id)
setData(val => ({
...val,
address_title: e.province_name + e.district_name + e.city_name + e.address_detail,
address_name: e.name,
address_phone: e.phone,
}))
}
return <>
<View className={styles.address_con} onClick={() => setShowList(true)}>
<IconFont name="icon-dizhiguanli" size={50} />
<View className={styles.message}>
<View className={styles.info_address}>
<View className={styles.address_name}>{data.address_title || '请选择收货地址'}</View>
<IconFont name="icon-rukou" color="#979797FF" />
</View>
<View className={styles.info_phone}>
<Text>{`${data.address_name} ${data.address_phone}`}</Text>
<Text>{data.address_mode}</Text>
</View>
</View>
</Popup>
</View>
</View>
<SelectAddress show={showList} onClose={() => setShowList(false)} onSelect={getAddress} />
</>
}

View File

@ -1,51 +1,27 @@
.card_con {
background-color: #ffffff;
padding: 0 24px;
margin-top: 24px;
box-sizing: border-box;
border-radius: 16px;
.card_header {
height: 82px;
font-size: 28px;
color: rgba(0, 0, 0, 0.8);
font-weight: 500;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
line-height: 82px;
}
.card_list {
.card_item {
height: 140px;
display: flex;
padding-top: 24px;
color: rgba(0, 0, 0, 0.8);
.card_item {
height: 140px;
display: flex;
padding-top: 24px;
color: rgba(0, 0, 0, 0.8);
.img {
width: 108px;
height: 108px;
}
.name_count {
width: 100%;
margin-left: 42px;
flex: 1;
font-size: 28px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
.btns {
width: 100%;
display: flex;
justify-content: flex-end;
}
.count_btn {
margin-top: 27px;
width: 170px;
}
}
}
.express_btn {
font-size: 28px;
color: #f64861;
.img {
width: 108px;
height: 108px;
}
.name_count {
width: 100%;
margin-left: 42px;
flex: 1;
font-size: 28px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
.btns {
width: 100%;
text-align: right;
padding: 32px 0 24px 0;
display: flex;
justify-content: flex-end;
}
.count_btn {
margin-top: 27px;
width: 170px;
}
}
}

View File

@ -1,49 +1,81 @@
import { Text, View } from '@tarojs/components'
import Taro, { getCurrentPages, useDidShow } from '@tarojs/taro'
import { memo, useCallback, useEffect, useState } from 'react'
import styles from './index.module.scss'
import Counter from '@/components/counter'
import LabAndImg from '@/components/LabAndImg'
export default () => {
return <View className={styles.card_con}>
<View className={styles.card_header}></View>
<View className={styles.card_list}>
<View className={styles.card_item}>
<View className={styles.img}><LabAndImg value={{}} /></View>
<View className={styles.name_count}>
<Text>()</Text>
<View className={styles.btns}>
<View className={styles.count_btn}>
<Counter
minNum={1}
maxNum={2}
defaultNum={1}
unit="米"
returnZero
/>
</View>
</View>
</View>
</View>
<View className={styles.card_item}>
<View className={styles.img}><LabAndImg value={{}} /></View>
<View className={styles.name_count}>
<Text>()</Text>
<View className={styles.btns}>
<View className={styles.count_btn}>
<Counter
minNum={1}
maxNum={2}
defaultNum={1}
unit="米"
returnZero
/>
</View>
</View>
</View>
</View>
<View className={styles.express_btn}></View>
</View>
</View>
interface ProductItemParamType {
code: string
id: number
name: string
}
export interface ParamItem {
id: number
affiliation_product: ProductItemParamType[]
color_card_name: string
texture_url: string
lab: { l: number; a: number; b: number }
rgb: { r: number; g: number; b: number }
is_add: boolean
count?: number
}
export interface Param {
value: ParamItem
onChangeNum?: (val: { id: number; count: number }) => void
onDelData?: (val: number) => void
}
export default memo((props: Param) => {
return <ProductItem onChangeNum={props.onChangeNum} onDelData={props.onDelData} value={props.value} />
})
const ProductItem = memo((props: Param) => {
const { value } = props
const labAndImgObj = useCallback(
(item) => {
return { lab: item.lab, rgb: item.rgb, texture_url: item.texture_url }
},
[value],
)
const onChangeNum = (num) => {
props.onChangeNum?.({ id: value.id, count: num })
}
console.log('测试:::', value)
const onMin = () => {
Taro.showModal({
title: '确认删除所选色卡?',
success(res) {
if (res.confirm) {
props?.onDelData?.(value.id)
}
else if (res.cancel) {
props.onChangeNum?.({ id: value.id, count: 1 })
}
},
})
}
return <>
<View key={value.id} className={styles.card_item}>
<View className={styles.img}><LabAndImg value={labAndImgObj(props)} /></View>
<View className={styles.name_count}>
<Text>{value.color_card_name}</Text>
<View className={styles.btns}>
<View className={styles.count_btn}>
<Counter
minNum={1}
maxNum={2}
defaultNum={value.count}
onClickBtn={onChangeNum}
onBlue={onChangeNum}
unit="件"
onMin={onMin}
/>
</View>
</View>
</View>
</View>
</>
})

View File

@ -1,14 +1,29 @@
import { Text, View } from '@tarojs/components'
import { useState } from 'react'
import styles from './index.module.scss'
import Remark from '@/components/remark'
export default () => {
return <View className={styles.remarks}>
<View className={styles.remarks_header}>
<Text></Text>
<Text>/</Text>
</View>
<View className={styles.remarks_message}>
<Text></Text>
</View>
</View>
interface Param {
onSave?: (val: string) => void
}
export default (props: Param) => {
const [showRemark, setShowRemark] = useState(false)
const [data, setData] = useState('')
const getOnSave = (e: string) => {
setData(e)
props.onSave?.(e)
setShowRemark(false)
}
return <>
<View className={styles.remarks} onClick={() => setShowRemark(true)}>
<View className={styles.remarks_header}>
<Text></Text>
<Text>/</Text>
</View>
<View className={styles.remarks_message}>
<Text>{data || '尚未备注信息'}</Text>
</View>
</View>
<Remark show={showRemark} onSave={getOnSave} onClose={() => setShowRemark(false)} />
</>
}

View File

@ -2,6 +2,7 @@
min-height: 100vh;
background-color: #f7f7f7ff;
padding: 24px;
padding-bottom: 180px;
.add_card_btn {
height: 82px;
background: #ffffff;
@ -12,6 +13,30 @@
color: #337fff;
margin-top: 24px;
}
.card_con {
background-color: #ffffff;
padding: 0 24px;
margin-top: 24px;
box-sizing: border-box;
border-radius: 16px;
.card_header {
height: 82px;
font-size: 28px;
color: rgba(0, 0, 0, 0.8);
font-weight: 500;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
line-height: 82px;
}
.card_list {
.express_btn {
font-size: 28px;
color: #f64861;
width: 100%;
text-align: right;
padding: 32px 0 24px 0;
}
}
}
.order_btn {
position: fixed;

View File

@ -1,18 +1,105 @@
import { Text, View } from '@tarojs/components'
import Taro, { getCurrentPages, useDidShow } from '@tarojs/taro'
import { useCallback, useMemo, useRef, useState } from 'react'
import styles from './index.module.scss'
import Address from './components/address'
import type { ParamItem } from './components/productCard'
import ProductCard from './components/productCard'
import Remark from './components/remark'
import { alert, goLink } from '@/common/common'
import { SubmitColorCardApi } from '@/api/colorCard'
import { getFilterData } from '@/common/util'
export interface submitData {
address_id: number
color_card_infos: { count: number; id: number }[]
remark: string
}
export default () => {
const submitData = useRef<submitData>({
address_id: 0,
color_card_infos: [],
remark: '',
})
const getAddress = (id: number) => {
submitData.current.address_id = id
}
const [list, setList] = useState<ParamItem[]>([])
useDidShow(() => {
const res = Taro.getStorageSync('colorCard') ? JSON.parse(Taro.getStorageSync('colorCard')) : []
setList(() => res)
computeCount(res)
Taro.removeStorageSync('colorCard')
})
const onAddCard = () => {
Taro.setStorageSync('colorCard', JSON.stringify(list))
Taro.navigateTo({
url: '/pages/getColorCard/index',
})
}
const onDelData = useCallback((id) => {
if (list.length === 1) { return alert.none('不能删除最后一个色卡') }
const res = list?.filter((item) => {
return item.id != id
})
computeCount(res)
setList(() => res)
}, [list])
// 计算总数
const [numText, setNumText] = useState('')
const computeCount = (list) => {
let res = 0
list.map(item => res += item.count)
setNumText(() => `当前共 ${list.length} 种色卡, 共 ${res}`)
}
const onChangeNum = useCallback((val: { id: number; count: number }) => {
list?.map((item) => {
if (item.id == val.id) {
item.count = val.count
}
})
setList(() => list)
computeCount(list)
}, [list])
const { fetchData: submitFetchData } = SubmitColorCardApi()
const onSubmitData = async() => {
submitData.current.color_card_infos = []
list?.map((item) => {
submitData.current.color_card_infos.push({
count: item.count || 0,
id: item.id,
})
})
if (!submitData.current.address_id) { return alert.none('请选择收货地址') }
const res = await submitFetchData(getFilterData(submitData.current))
if (res.success) {
alert.success('提交成功')
}
}
const onRemark = (e) => {
submitData.current.remark = e
}
return <View className={styles.main}>
<Address />
<View className={styles.add_card_btn}></View>
<ProductCard />
<Remark />
<Address onSelect={getAddress} />
<View className={styles.add_card_btn} onClick={onAddCard}></View>
<View className={styles.card_con}>
<View className={styles.card_header}></View>
<View className={styles.card_list}>
{list?.map(item => <ProductCard key={item.id} value={item} onDelData={onDelData} onChangeNum={onChangeNum} />)}
<View className={styles.express_btn}></View>
</View>
</View>
<Remark onSave={onRemark} />
<View className={styles.order_btn}>
<View className={styles.btn_con}>
<Text> 1 , 3 </Text>
<View className={styles.btn_con} onClick={onSubmitData}>
<Text>{numText}</Text>
<View className={styles.btn}></View>
</View>
</View>

View File

@ -0,0 +1,39 @@
.address_con {
display: flex;
padding: 32px;
background-color: #ffffffff;
border-radius: 16px;
.message {
display: flex;
flex-direction: column;
width: 100%;
margin-left: 24px;
.info_address {
font-size: 28px;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
padding-bottom: 16px;
.address_name {
color: rgba(0, 0, 0, 0.8);
width: 461px;
}
}
.info_phone {
display: flex;
padding-top: 32px;
justify-content: space-between;
font-size: 28px;
color: rgba(0, 0, 0, 0.8);
text {
display: flex;
align-items: center;
&:nth-child(2) {
color: #337fffff;
}
}
}
}
}

View File

@ -0,0 +1,48 @@
import { Text, View } from '@tarojs/components'
import { useEffect, useState } from 'react'
import styles from './index.module.scss'
import IconFont from '@/components/iconfont/iconfont'
import AddressList from '@/components/AddressList'
import Popup from '@/components/popup'
import SelectAddress from '@/components/selectAddress'
interface Param {
defaultValue: {
address_title: string
address_name: string
address_phone: string
}
}
export default (props: Param) => {
const [data, setData] = useState({
address_title: '',
address_name: '',
address_phone: '',
address_mode: '物流',
})
useEffect(() => {
if (props.defaultValue) {
setData(e => ({
...e,
address_title: props.defaultValue.address_title,
address_name: props.defaultValue.address_name,
address_phone: props.defaultValue.address_phone,
}))
}
}, [props.defaultValue])
return <>
<View className={styles.address_con} >
<IconFont name="icon-dizhiguanli" size={50} />
<View className={styles.message}>
<View className={styles.info_address}>
<View className={styles.address_name}>{data.address_title || '请选择收货地址'}</View>
</View>
<View className={styles.info_phone}>
<Text>{`${data.address_name} ${data.address_phone}`}</Text>
<Text>{data.address_mode}</Text>
</View>
</View>
</View>
</>
}

View File

@ -0,0 +1,38 @@
.order_info {
height: 227px;
background: #ffffff;
border-radius: 16px;
padding: 0 32px;
margin-top: 24px;
.order_info_title {
height: 82px;
line-height: 82px;
font-size: 28px;
color: rgba(0, 0, 0, 0.8);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.order_info_list {
font-size: 28px;
.order_info_item {
display: flex;
justify-content: space-between;
margin-top: 24px;
.left {
color: rgba(0, 0, 0, 0.4);
}
.right {
display: flex;
.copy_btn {
width: 65px;
height: 32px;
border-radius: 8px;
border: 1px solid #337fff;
text-align: center;
line-height: 32px;
color: #337fffff;
margin-left: 10px;
}
}
}
}
}

View File

@ -0,0 +1,21 @@
import { Text, View } from '@tarojs/components'
import styles from './index.module.scss'
export default () => {
return <View className={styles.order_info}>
<View className={styles.order_info_title}></View>
<View className={styles.order_info_list}>
<View className={styles.order_info_item}>
<Text className={styles.left}></Text>
<View className={styles.right}>
<Text>XS-LY-2208240001</Text>
<View className={styles.copy_btn}></View>
</View>
</View>
<View className={styles.order_info_item}>
<Text className={styles.left}></Text>
<View className={styles.right}>2022-08-24 14:54:21</View>
</View>
</View>
</View>
}

View File

@ -0,0 +1,51 @@
.card_con {
background-color: #ffffff;
padding: 0 24px;
margin-top: 24px;
box-sizing: border-box;
border-radius: 16px;
.card_header {
height: 82px;
font-size: 28px;
color: rgba(0, 0, 0, 0.8);
font-weight: 500;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
line-height: 82px;
}
.card_list {
.card_item {
height: 140px;
display: flex;
padding-top: 24px;
color: rgba(0, 0, 0, 0.8);
.img {
width: 108px;
height: 108px;
}
.name_count {
width: 100%;
margin-left: 42px;
flex: 1;
font-size: 28px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
.btns {
width: 100%;
display: flex;
justify-content: flex-end;
}
.count_btn {
margin-top: 27px;
width: 170px;
}
}
}
.express_btn {
font-size: 28px;
color: #f64861;
width: 100%;
text-align: right;
padding: 32px 0 24px 0;
}
}
}

View File

@ -0,0 +1,49 @@
import { Text, View } from '@tarojs/components'
import styles from './index.module.scss'
import Counter from '@/components/counter'
import LabAndImg from '@/components/LabAndImg'
export default () => {
return <View className={styles.card_con}>
<View className={styles.card_header}></View>
<View className={styles.card_list}>
<View className={styles.card_item}>
<View className={styles.img}><LabAndImg value={{}} /></View>
<View className={styles.name_count}>
<Text>()</Text>
<View className={styles.btns}>
<View className={styles.count_btn}>
<Counter
minNum={1}
maxNum={2}
defaultNum={1}
unit="米"
returnZero
/>
</View>
</View>
</View>
</View>
<View className={styles.card_item}>
<View className={styles.img}><LabAndImg value={{}} /></View>
<View className={styles.name_count}>
<Text>()</Text>
<View className={styles.btns}>
<View className={styles.count_btn}>
<Counter
minNum={1}
maxNum={2}
defaultNum={1}
unit="米"
returnZero
/>
</View>
</View>
</View>
</View>
<View className={styles.express_btn}></View>
</View>
</View>
}

View File

@ -0,0 +1,25 @@
.remarks {
height: 165px;
background: #ffffff;
border-radius: 16px;
margin-top: 24px;
padding: 0 32px;
font-size: 28px;
.remarks_header {
display: flex;
height: 80px;
line-height: 80px;
justify-content: space-between;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
text {
&:nth-child(2) {
color: rgba(0, 0, 0, 0.8);
}
}
}
.remarks_message {
height: 82px;
line-height: 82px;
color: rgba(0, 0, 0, 0.4);
}
}

View File

@ -0,0 +1,21 @@
import { Text, View } from '@tarojs/components'
import { useState } from 'react'
import styles from './index.module.scss'
import Remark from '@/components/remark'
interface Param {
value: string
}
export default (props: Param) => {
return <>
<View className={styles.remarks} >
<View className={styles.remarks_header}>
<Text></Text>
<Text></Text>
</View>
<View className={styles.remarks_message}>
<Text>{props.value || '尚未备注信息'}</Text>
</View>
</View>
</>
}

View File

@ -0,0 +1,4 @@
export default {
navigationBarTitleText: '色卡订单详情',
enableShareAppMessage: true,
}

View File

@ -0,0 +1,45 @@
.main {
min-height: 100vh;
background-color: #f7f7f7ff;
padding: 24px;
.add_card_btn {
height: 82px;
background: #ffffff;
border-radius: 16px;
border: 1px solid #337fff;
text-align: center;
line-height: 82px;
color: #337fff;
margin-top: 24px;
}
.order_btn {
position: fixed;
height: 162px;
background: #ffffff;
box-shadow: 0px -5px 20px -8px rgba(0, 0, 0, 0.06);
width: 100%;
bottom: 0;
left: 0;
padding: 0 24px;
display: flex;
justify-content: space-between;
box-sizing: border-box;
.btn_con {
display: flex;
align-items: center;
justify-content: flex-end;
width: 100%;
height: 100px;
}
.btn {
width: 195px;
height: 72px;
border: 1px solid rgba(0, 0, 0, 0.6);
border-radius: 40px;
text-align: center;
line-height: 72px;
color: #000000;
}
}
}

View File

@ -0,0 +1,29 @@
import { Text, View } from '@tarojs/components'
import { useState } from 'react'
import styles from './index.module.scss'
import Address from './components/address'
import ProductCard from './components/productCard'
import Remark from './components/remark'
import OrderInfo from './components/orderInfo'
import { goLink } from '@/common/common'
import SearchInput from '@/components/searchInput'
export default () => {
const [data, setData] = useState({
address_title: '广东省佛山市禅城区南庄镇吉利大道872巷备份',
address_name: '谭先生',
address_phone: '13334726540',
address_mode: '物流',
})
return <View className={styles.main}>
<Address defaultValue={data} />
<ProductCard />
<OrderInfo />
<Remark value="被设计费开始减肥开始减肥" />
<View className={styles.order_btn}>
<View className={styles.btn_con}>
<View className={styles.btn}></View>
</View>
</View>
</View>
}

View File

@ -15,13 +15,12 @@
}
.card_info_label {
display: grid;
grid-template-columns: repeat(3, 85px);
grid-template-columns: repeat(3, 100px);
grid-gap: 10px 10px;
margin-top: 10px;
text {
font-size: 24px;
color: #4581ff;
width: 85px;
height: 34px;
text-align: center;
line-height: 34px;

View File

@ -1,29 +1,53 @@
import { Text, View } from '@tarojs/components'
import { useState } from 'react'
import { memo, useState } from 'react'
import styles from './index.module.scss'
import LabAndImg from '@/components/LabAndImg'
import Checkbox from '@/components/checkbox'
export default () => {
interface ProductItemParamType {
code: string
id: number
name: string
}
export interface ParamType {
id: number
affiliation_product: ProductItemParamType[]
color_card_name: string
texture_url: string
lab: { l: number; a: number; b: number }
rgb: { r: number; g: number; b: number }
is_add: boolean
onSelect?: (val: ParamType, status: boolean) => void
count?: number
}
export default memo((props: ParamType) => {
const { affiliation_product, color_card_name = '', texture_url = '', lab, rgb } = props
const [checkStatus, setCheckStatus] = useState(false)
const changeSelect = () => {
setCheckStatus(!checkStatus)
props.onSelect?.(props, !checkStatus)
}
const onSelect = () => {
props.onSelect?.(props, true)
setCheckStatus(true)
}
const onClose = () => {
props.onSelect?.(props, false)
setCheckStatus(false)
}
return <View className={styles.get_card_item} onClick={changeSelect}>
<View className={styles.image}>
<LabAndImg value={{}} />
</View>
<View className={styles.card_info}>
<View className={styles.card_info_name}>()</View>
<View className={styles.card_info_name}>{color_card_name}</View>
<View className={styles.card_info_label}>
<Text>0042</Text>
<Text>0042</Text>
<Text>0042</Text>
<Text>0042</Text>
{affiliation_product?.map(item => <Text key={item.id}>{item.code}</Text>)}
</View>
</View>
<View className={styles.checkBox}>
<Checkbox status={checkStatus} onSelect={() => setCheckStatus(true)} onClose={() => setCheckStatus(false)} />
<View className={styles.checkBox} onClick={e => e.stopPropagation()}>
<Checkbox status={props.is_add ? true : checkStatus} disabled={props.is_add} onSelect={onSelect} onClose={onClose} />
</View>
</View>
}
})

View File

@ -1,39 +1,130 @@
import { Image, Text, View } from '@tarojs/components'
import { useRef, useState } from 'react'
import Taro, { getCurrentPages, useDidShow } from '@tarojs/taro'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import classNames from 'classnames'
import styles from './index.module.scss'
import type { ParamType } from './components/productItem'
import ProductItem from './components/productItem'
import InfiniteScroll from '@/components/infiniteScroll'
import Search from '@/components/search'
import { GetColorCardApi } from '@/api/colorCard'
import { dataLoadingStatus, getFilterData } from '@/common/util'
export default () => {
const [search, setSearch] = useState<string>()
const { fetchData, state: cardState } = GetColorCardApi()
const [colorCardData, setColorCardData] = useState<{ list: ParamType[]; total: number }>({
list: [],
total: 0,
})
const [searchData, setSearchData] = useState<{ color_card_ids?: number[]; name?: string; page: number; size: number }>({
page: 1,
size: 10,
})
const shopColorCardData = useRef<ParamType[]>([])
// 获取已加入购物车的数据id
const getShopId = () => {
if (shopColorCardData.current.length <= 0) { return null }
return shopColorCardData.current?.map((item) => {
return item.id
})
}
// 获取数据
const getGetColorCard = async() => {
console.log('getShopId():::', getShopId())
const { data } = await fetchData(getFilterData({ ...searchData, color_card_ids: getShopId() }))
setColorCardData(() => ({ list: data.list, total: data.total }))
setRefresherTriggeredStatus(() => false)
}
useEffect(() => {
if (Taro.getStorageSync('colorCard') && shopColorCardData.current.length <= 0) {
shopColorCardData.current = Taro.getStorageSync('colorCard') ? JSON.parse(Taro.getStorageSync('colorCard')) : []
// Taro.removeStorageSync('colorCard')
}
getGetColorCard()
}, [searchData])
const getSearch = (con) => {
setSearch(con)
setSearchData(e => ({ ...e, name: con }))
}
const onReset = () => {
setSearch('')
setSearchData(e => ({ ...e, name: '' }))
}
// 选择的数据
const [selectList, setSelectList] = useState<ParamType[]>([])
// 数据加载状态
const statusMore = useMemo(() => {
return dataLoadingStatus({ list: colorCardData.list, total: cardState.total, status: cardState.loading })
}, [colorCardData, cardState])
// 上拉加载数据
const pageNum = useRef({ size: searchData.size, page: searchData.page })
const getScrolltolower = useCallback(() => {
if (colorCardData.list.length < colorCardData.total) {
pageNum.current.page++
const size = pageNum.current.size * pageNum.current.page
setSearchData(e => ({ ...e, size }))
}
}, [colorCardData])
// 列表下拉刷新
const [refresherTriggeredStatus, setRefresherTriggeredStatus] = useState(false)
const getRefresherRefresh = async() => {
pageNum.current.size = 1
setRefresherTriggeredStatus(true)
setSearchData(val => ({ ...val, size: 10 }))
}
const onSubmit = () => {
selectList?.map((item) => {
item.count = 1
})
Taro.setStorageSync('colorCard', JSON.stringify([...selectList, ...shopColorCardData.current]))
Taro.redirectTo({
url: '/pages/colorCardOrder/index',
})
}
const onSelectData = (val, status) => {
if (status) {
setSelectList(e => [...e, val])
}
else {
const res = selectList?.filter((item) => {
return val.id != item.id
})
setSelectList(e => res)
}
}
return <View className={styles.main}>
<View className={styles.search}>
<Search defaultValue={search} placeholder="请输入搜索面料/色卡" changeOnSearch={getSearch} />
<Search defaultValue={searchData?.name} placeholder="请输入搜索面料/色卡" changeOnSearch={getSearch} debounceTime={300} />
<View className={styles.btn_reset} onClick={onReset}></View>
</View>
<View className={styles.get_card_con}>
<InfiniteScroll
statusMore={2}
selfonScrollToLower={getScrolltolower}
refresherTriggered={refresherTriggeredStatus}
statusMore={statusMore}
refresherEnabled
selfOnRefresherRefresh={getRefresherRefresh}
>
{new Array(10).fill('').map((item) => {
{colorCardData.list?.map((item) => {
return (
<View className={styles.get_card_list} key={item.id}>
<ProductItem />
<ProductItem {...item} onSelect={onSelectData} />
</View>
)
})}
</InfiniteScroll>
</View>
<View className={styles.get_card_btn} >
<View className={styles.get_card_btn} onClick={onSubmit}>
<Text></Text>
</View>
</View>