feat(领取剪样):

This commit is contained in:
czm 2023-02-20 20:25:44 +08:00
parent dd69400dfa
commit 2d2518f4ab
25 changed files with 1108 additions and 159 deletions

View File

@ -7,7 +7,7 @@ import { useRequest as request } from '@/use/useHttp'
export const GetCutSampleOrderListApi = () => {
return request({
url: '/v1/mall/cutSampleOrder/list',
method: 'post',
method: 'get',
})
}
@ -17,7 +17,7 @@ export const GetCutSampleOrderListApi = () => {
*/
export const GetCutSampleOrderStatusApi = () => {
return request({
url: '/v1/mall/cutSampleOrder/status',
url: '/v1/mall/cutSampleOrder/audit_status',
method: 'get',
})
}
@ -26,53 +26,20 @@ export const GetCutSampleOrderStatusApi = () => {
*
* @returns
*/
export const ColorCardOrderCancelApi = () => {
export const CutSampleOrderCancelApi = () => {
return request({
url: '/v1/mall/colorCardOrder/cancel',
url: '/v1/mall/cutSampleOrder/cancel',
method: 'post',
})
}
/**
*
*
* @returns
*/
export const SubmitColorCardApi = () => {
export const GetSampleOrderProductApi = () => {
return request({
url: '/v1/mall/colorCardOrder/submit',
method: 'post',
})
}
/**
*
* @returns
*/
export const GetColorCardOrderApi = () => {
return request({
url: '/v1/mall/colorCardOrder/list',
method: 'get',
})
}
/**
*
* @returns
*/
export const GetColorCardOrderDetailApi = () => {
return request({
url: '/v1/mall/colorCardOrder',
method: 'get',
})
}
/**
*
* @returns
*/
export const GetColorCardOrderByProductApi = () => {
return request({
url: '/v1/mall/product/colorCard',
url: '/v1/mall/cutSampleOrder/products',
method: 'get',
})
}

View File

@ -242,5 +242,11 @@ export default {
'index',
],
},
{
root: 'pages/cutSampleListOrderDetail',
pages: [
'index',
],
},
],
}

View File

@ -13,8 +13,8 @@
// export const BASE_URL = 'https://www.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.28:50001/lymarket' // 婷
// export const BASE_URL = 'http://192.168.1.42:50002/lymarket' // 杰
// CDN
// 生成密钥

View File

@ -11,11 +11,6 @@ import { formatHashTag } from '@/common/fotmat'
import colorItem from '@/pages/codeList/components/colorItem'
import { goLink } from '@/common/common'
export interface Param {
show: boolean
product_id: number
onClose?: () => void
}
export interface ColorItem {
bulk_price: number
code: string
@ -35,18 +30,27 @@ export interface ColorItem {
count?: number
}
export interface Param {
show: boolean
product_id: number
onClose?: () => void
onSelected?: (val: ColorItem[]) => void
defaultValueIds?: number[]
}
export default memo((props: Param) => {
const { show = false, onClose, product_id } = props
const { show = false, onClose, product_id, onSelected, defaultValueIds = [] } = props
const [colorList, setColorList] = useState<ColorItem[]>([])
const { fetchData: productFetchData } = GetProductDetailApi()
const getProductDetail = async() => {
const res = await productFetchData({ id: product_id })
setColorList(res.data.product_color_list || [])
setColorList(initData(res.data.product_color_list) || [])
}
useEffect(() => {
(show && product_id) && getProductDetail()
!show && setColorList([])
}, [show, product_id])
const colorListRef = useRef<ColorItem[]>([])
@ -54,6 +58,20 @@ export default memo((props: Param) => {
colorListRef.current = colorList
}, [colorList])
const initData = (data) => {
if (defaultValueIds.length > 0) {
return data.map((item, index) => {
if (defaultValueIds.includes(item.id)) {
return data[index] = { ...item, status: true }
}
return item
})
}
else {
return data
}
}
const onSelect = useCallback((val: ColorItem) => {
colorListRef.current.map((item, index) => {
if (item.id === val.id) {
@ -74,8 +92,9 @@ export default memo((props: Param) => {
colorList?.map((item) => {
if (item.status) { data.push({ ...item, count: 1 }) }
})
Taro.setStorageSync('cutSample', JSON.stringify(data))
goLink('/pages/cutSampleListOrder/index')
onSelected?.(data)
// Taro.setStorageSync('cutSample', JSON.stringify(data))
// goLink('/pages/cutSampleListOrder/index')
}
return <View className={styles.main}>
<Popup show={show} showTitle={false} onClose={onClose}>

View File

@ -0,0 +1,88 @@
.list_item {
padding: 0 24px;
margin-top: 20px;
width: 100%;
box-sizing: border-box;
background-color: #fff;
border-radius: 16px;
padding-bottom: 20px;
.item_header {
height: 82px;
display: flex;
justify-content: space-between;
align-items: center;
color: #000000ff;
font-size: 28px;
font-weight: 500;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
text {
&:nth-child(2) {
color: #0d7cffff;
}
}
}
.item_con {
display: flex;
padding: 24px 0;
box-sizing: border-box;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
.image {
width: 134px;
height: 134px;
}
.item_con_desc {
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
font-size: 28px;
.item_con_name {
width: 100%;
display: flex;
justify-content: space-between;
padding-left: 24px;
box-sizing: border-box;
}
.item_con_color_list {
padding-left: 24px;
box-sizing: border-box;
.color_item {
display: flex;
justify-content: space-between;
color: rgba(0, 0, 0, 0.6);
}
}
.item_con_count {
text-align: right;
color: rgba(0, 0, 0, 0.6);
}
}
}
.card_info {
font-size: 24px;
display: flex;
justify-content: space-between;
margin-top: 16px;
color: rgba(0, 0, 0, 0.4);
}
.express {
color: #f64861ff;
font-size: 28px;
text-align: right;
margin-top: 16px;
}
.btns {
padding-top: 32px;
display: flex;
justify-content: flex-end;
text {
display: inline-block;
width: 195px;
height: 72px;
border-radius: 40px;
border: 1px solid rgba(0, 0, 0, 0.06);
text-align: center;
line-height: 72px;
}
}
}

View File

@ -0,0 +1,84 @@
import { Text, View } from '@tarojs/components'
import { useMemo } from 'react'
import styles from './index.module.scss'
import LabAndImg from '@/components/LabAndImg'
import { goLink } from '@/common/common'
import { formatHashTag } from '@/common/fotmat'
interface order_product_item {
code: string
lab: { l: number; a: number; b: number }
name: string
rgb: { r: number; g: number; b: number }
product_id: number
texture_url: string
product_colors: {
code: string
color_num: number
lab: { l: number; a: number; b: number }
name: string
product_color_id: number
rgb: { r: number; g: number; b: number }
texture_url: string
}[]
}
export interface ParamItem {
id: number
order_id: number
order_no: string
mp_cut_sample_audit_status: number
mp_cut_sample_audit_status_name: string
shipment_mode: number
shipment_mode_name: string
cut_sample_order_product_list: order_product_item[]
total_colors: number
total_fabrics: number
total_number: number
}
interface Param {
value: ParamItem
onCancel?: (val: number) => void
}
export default (props: Param) => {
const { value, onCancel } = props
const card_one = useMemo(() => {
return value.cut_sample_order_product_list ? value.cut_sample_order_product_list[0] : null
}, [value])
const onCancelEven = (e, id: number) => {
e.stopPropagation()
onCancel?.(id)
}
return <View className={styles.list_item} onClick={() => goLink('/pages/colorCardOrderDetail/index', { id: value.order_id })} >
<View className={styles.item_header}>
<Text>{value.order_no}</Text>
<Text>{value.mp_cut_sample_audit_status_name}</Text>
</View>
<View className={styles.item_con}>
<View className={styles.image}>
<LabAndImg value={{}} showStatus={false} />
</View>
<View className={styles.item_con_desc}>
<View className={styles.item_con_name}>
<Text>{card_one?.name}</Text>
<Text>{value.shipment_mode_name}</Text>
</View>
<View className={styles.item_con_color_list}>
{card_one?.product_colors?.map((citem, index) => <View key={citem.product_color_id} className={styles.color_item}>
{index < 2 && <><Text>{formatHashTag(citem.code, citem.name)}</Text>
<Text>x{citem.color_num}</Text></>}
</View>)}
</View>
</View>
</View>
<View className={styles.card_info}>
<Text>:</Text>
<Text>{value.total_fabrics}{value.total_colors} {value.total_number} </Text>
</View>
<View className={styles.express}></View>
{value.mp_cut_sample_audit_status === 1 && <View className={styles.btns} onClick={e => onCancelEven?.(e, value.order_id)}><Text></Text></View>}
</View>
}

View File

@ -2,18 +2,18 @@ import { Image, Text, View } from '@tarojs/components'
import Taro, { useDidShow } from '@tarojs/taro'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import classNames from 'classnames'
import type { ParamItem } from '../productItem'
import ProductItem from '../productItem'
import type { ParamItem } from '../cutProductItem'
import CutProductItem from '../cutProductItem'
import styles from './index.module.scss'
import InfiniteScroll from '@/components/infiniteScroll'
import { alert, goLink } from '@/common/common'
import { dataLoadingStatus, getFilterData } from '@/common/util'
import kong from '@/styles/image/kong.png'
import { GetCutSampleOrderListApi, GetCutSampleOrderStatusApi } from '@/api/cutSample'
import { CutSampleOrderCancelApi, GetCutSampleOrderListApi, GetCutSampleOrderStatusApi } from '@/api/cutSample'
export default () => {
const [searchData, setSearchData] = useState<{ status?: number; page: number; size: number }>({
status: 0,
const [searchData, setSearchData] = useState<{ mp_cut_sample_audit_status?: number; page: number; size: number }>({
mp_cut_sample_audit_status: 0,
page: 1,
size: 10,
})
@ -24,24 +24,24 @@ export default () => {
})
const { fetchData: fetchDataOrder, state: OrderState } = GetCutSampleOrderListApi()
const getColorCardOrder = async() => {
const getOrder = async() => {
const res = await fetchDataOrder(getFilterData(searchData))
setRefresherTriggeredStatus(false)
setOrderData(() => res.data)
}
useEffect(() => {
getColorCardOrder()
getOrder()
}, [searchData])
useDidShow(() => {
getColorCardOrderStatus()
})
useEffect(() => {
getOrderStatus()
}, [])
// 获取状态列表
const [statusList, setStatusList] = useState<{ id: 0|1|2; name: string }[]>([])
const { fetchData: fetchDataStatus } = GetCutSampleOrderStatusApi()
const getColorCardOrderStatus = async() => {
const getOrderStatus = async() => {
const res = await fetchDataStatus()
setStatusList([{ id: 0, name: '全部记录' }, ...res.data.list])
}
@ -71,32 +71,32 @@ export default () => {
const changeStatus = (index: number) => {
pageNum.current.page = 1
setSearchData(e => ({ ...e, status: index, page: 1, size: 10 }))
setSearchData(e => ({ ...e, mp_cut_sample_audit_status: index, page: 1, size: 10 }))
}
// 取消订单
// const { fetchData: fetchDataCancel } = ColorCardOrderCancelApi()
// const onCancel = async(id: number) => {
// Taro.showModal({
// title: '确定取消订单?',
// async success(res) {
// if (res.confirm) {
// const res = await fetchDataCancel({ id })
// if (res.success) {
// alert.success('取消成功')
// getColorCardOrder()
// }
// }
// else if (res.cancel) {
// console.log('用户点击取消')
// }
// },
// })
// }
const { fetchData: fetchDataCancel } = CutSampleOrderCancelApi()
const onCancel = async(id: number) => {
Taro.showModal({
title: '确定取消订单?',
async success(res) {
if (res.confirm) {
const res = await fetchDataCancel({ id })
if (res.success) {
alert.success('取消成功')
getOrder()
}
}
else if (res.cancel) {
console.log('用户点击取消')
}
},
})
}
return <>
<View className={styles.btn_list}>
{statusList.map(item => <View key={item.id} onClick={() => changeStatus(item.id)} className={classNames(styles.btn_item, searchData.status === item.id && styles.select_ed)}>{item.name}</View>)}
{statusList.map(item => <View key={item.id} onClick={() => changeStatus(item.id)} className={classNames(styles.btn_item, searchData.mp_cut_sample_audit_status === item.id && styles.select_ed)}>{item.name}</View>)}
</View>
<View className={styles.con}>
{false && <View className={styles.kong_image}>
@ -114,7 +114,7 @@ export default () => {
{orderData.list?.map((item) => {
return (
<View key={item.id} className={styles.order_item_con}>
<ProductItem value={item} onCancel={onCancel} />
<CutProductItem value={item} onCancel={onCancel} />
</View>
)
})}

View File

@ -4,13 +4,16 @@ import PopupSelectColor from '../popupSelectColor'
import styles from './index.module.scss'
import LabAndImg from '@/components/LabAndImg'
import Checkbox from '@/components/checkbox'
import { formatHashTag } from '@/common/fotmat'
interface ProductItemParamType {
code: string
id: number
name: string
}
export interface ParamType {
export interface ParamItem {
code: string
id: number
affiliation_product: ProductItemParamType[]
color_card_name: string
@ -18,40 +21,53 @@ export interface ParamType {
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
component: string
craft: string
describe: string
hexadecimal_code: string
is_favorite: boolean
kind_code: string
kind_id: number
kind_name: string
name: string
product_color_count: number
product_screw_id: number
weight_density: string
width: string
}
export interface ParamType {
productItem: ParamItem
onSelect?: (val: ParamItem|null) => void
selected: boolean
}
export default memo((props: ParamType) => {
const { affiliation_product, color_card_name = '', texture_url = '', lab, rgb } = props
const { productItem = null, selected = false } = props
const [checkStatus, setCheckStatus] = useState(false)
const changeSelect = () => {
setCheckStatus(!checkStatus)
props.onSelect?.(props, !checkStatus)
props.onSelect?.(productItem)
}
const onSelect = () => {
props.onSelect?.(props, true)
props.onSelect?.(productItem)
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={{}} />
<Text>24</Text>
<Text>{productItem?.product_color_count}</Text>
</View>
<View className={styles.card_info}>
<View className={styles.card_info_name}>2S单面平纹()</View>
<View className={styles.card_info_name}>{formatHashTag(productItem?.code, productItem?.name)}</View>
<View className={styles.card_info_label}>
{new Array(2).fill('').map(item => <Text key={item.id}>170CM</Text>)}
</View>
<View className={styles.desc}>67.6%24%6.4%</View>
<View className={styles.desc}>{productItem?.craft}</View>
</View>
<View className={styles.checkBox} onClick={e => e.stopPropagation()}>
<View className={styles.add_btn} onClick={() => onSelect()}></View>
<View className={styles.add_btn} onClick={() => onSelect()}>{selected ? '继续添加' : '添加'}</View>
</View>
</View>

View File

@ -3,26 +3,28 @@ 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 type { ParamItem } from './components/productItem'
import ProductItem from './components/productItem'
import PopupSelectColor from './components/popupSelectColor'
import type { ColorItem } from '@/components/popupSelectColor'
import PopupSelectColor from '@/components/popupSelectColor'
import InfiniteScroll from '@/components/infiniteScroll'
import Search from '@/components/search'
import { GetColorCardApi } from '@/api/colorCard'
import { dataLoadingStatus, getFilterData } from '@/common/util'
import { GetSampleOrderProductApi } from '@/api/cutSample'
import { goLink } from '@/common/common'
export default () => {
const { fetchData, state: cardState } = GetColorCardApi()
const [colorCardData, setColorCardData] = useState<{ list: ParamType[]; total: number }>({
const { fetchData, state: cardState } = GetSampleOrderProductApi()
const [orderData, setOrderData] = useState<{ list: ParamItem[]; total: number }>({
list: [],
total: 0,
})
const [searchData, setSearchData] = useState<{ color_card_ids?: number[]; name?: string; page: number; size: number }>({
const [searchData, setSearchData] = useState<{ color_card_ids?: number[]; product_code_and_name?: string; page: number; size: number }>({
page: 1,
size: 10,
})
const shopColorCardData = useRef<ParamType[]>([])
const shopColorCardData = useRef<ParamItem[]>([])
// 获取已加入购物车的数据id
const getShopId = () => {
@ -34,44 +36,43 @@ export default () => {
// 获取数据
const getGetColorCard = async() => {
console.log('getShopId():::', getShopId())
const { data } = await fetchData(getFilterData({ ...searchData, color_card_ids: getShopId() }))
setColorCardData(() => ({ list: data.list, total: data.total }))
setOrderData(() => ({ 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')
if (Taro.getStorageSync('cutSample') && shopColorCardData.current.length <= 0) {
shopColorCardData.current = Taro.getStorageSync('cutSample') ? JSON.parse(Taro.getStorageSync('cutSample')) : []
// Taro.removeStorageSync('cutSample')
}
getGetColorCard()
}, [searchData])
const getSearch = (con) => {
setSearchData(e => ({ ...e, name: con }))
setSearchData(e => ({ ...e, product_code_and_name: con }))
}
const onReset = () => {
setSearchData(e => ({ ...e, name: '' }))
setSearchData(e => ({ ...e, product_code_and_name: '' }))
}
// 选择的数据
const [selectList, setSelectList] = useState<ParamType[]>([])
const [selectList, setSelectList] = useState<ParamItem[]>([])
// 数据加载状态
const statusMore = useMemo(() => {
return dataLoadingStatus({ list: colorCardData.list, total: cardState.total, status: cardState.loading })
}, [colorCardData, cardState])
return dataLoadingStatus({ list: orderData.list, total: cardState.total, status: cardState.loading })
}, [orderData, cardState])
// 上拉加载数据
const pageNum = useRef({ size: searchData.size, page: searchData.page })
const getScrolltolower = useCallback(() => {
if (colorCardData.list.length < colorCardData.total) {
if (orderData.list.length < orderData.total) {
pageNum.current.page++
const size = pageNum.current.size * pageNum.current.page
setSearchData(e => ({ ...e, size }))
}
}, [colorCardData])
}, [orderData])
// 列表下拉刷新
const [refresherTriggeredStatus, setRefresherTriggeredStatus] = useState(false)
@ -82,40 +83,73 @@ export default () => {
}
const onSubmit = () => {
selectList?.map((item) => {
item.count = 1
})
Taro.setStorageSync('colorCard', JSON.stringify([...selectList, ...shopColorCardData.current]))
Taro.setStorageSync('cutSample', JSON.stringify([...selectProcutColors, ...shopColorCardData.current]))
Taro.redirectTo({
url: '/pages/colorCardOrder/index',
url: '/pages/cutSampleListOrder/index',
})
}
const [showColorList, setShowColorList] = useState(false)
const onSelectData = (val, status) => {
const [selectItem, setSelectItem] = useState<ParamItem>()
const onSelectData = (val: ParamItem) => {
setShowColorList(true)
setSelectItem(val)
// 获取该面料下的颜色数据
const index = selectProsuctIds.indexOf(val.id)
if (index !== -1) {
const colorIds: number[] = []
selectProcutColors[index].colors?.map((citem) => {
colorIds.push(citem.id)
})
setSelectColorIds(colorIds)
}
}
const onClose = () => {
setShowColorList(false)
}
const [selectProcutColors, setSelectProcutColors] = useState < (ParamItem & { colors: ColorItem[] })[] > ([])
const [selectProsuctIds, setSelectProsuctIds] = useState<number[]>([])
const [selectColorIds, setSelectColorIds] = useState<number[]>([])
const onSelected = (val: ColorItem[]) => {
val.map((item) => {
item.count = 1
})
const pIndex = selectProcutColors?.findIndex(item => item.id === selectItem?.id)
if (pIndex === -1) {
const data: ParamItem&{ colors: ColorItem[] } = { ...selectItem }
data.colors = val
selectProcutColors.push(data)
}
else {
selectProcutColors[pIndex].colors = val
}
if (selectItem?.id && !selectProsuctIds.includes(selectItem?.id)) {
selectProsuctIds.push(selectItem?.id)
setSelectProsuctIds(selectProsuctIds)
}
setSelectProcutColors(selectProcutColors)
setShowColorList(false)
}
return <View className={styles.main}>
<View className={styles.search}>
<Search defaultValue={searchData?.name} placeholder="请输入搜索面料/色卡" changeOnSearch={getSearch} debounceTime={300} />
<Search defaultValue={searchData?.product_code_and_name} placeholder="请输入搜索面料" changeOnSearch={getSearch} debounceTime={300} />
<View className={styles.btn_reset} onClick={onReset}></View>
</View>
<View className={styles.get_card_con}>
<InfiniteScroll
// selfonScrollToLower={getScrolltolower}
// refresherTriggered={refresherTriggeredStatus}
statusMore={2}
selfonScrollToLower={getScrolltolower}
refresherTriggered={refresherTriggeredStatus}
statusMore={statusMore}
refresherEnabled
// selfOnRefresherRefresh={getRefresherRefresh}
selfOnRefresherRefresh={getRefresherRefresh}
>
{new Array(10).fill('').map((item) => {
{orderData.list?.map((item) => {
return (
<View className={styles.get_card_list} key={item.id}>
<ProductItem {...item} onSelect={onSelectData} />
<ProductItem selected={selectProsuctIds.includes(item.id)} productItem={item} onSelect={onSelectData} />
</View>
)
})}
@ -124,6 +158,6 @@ export default () => {
<View className={styles.get_card_btn} onClick={onSubmit}>
<Text></Text>
</View>
<PopupSelectColor show={showColorList} onClose={onClose} />
<PopupSelectColor defaultValueIds={selectColorIds} onSelected={onSelected} show={showColorList} product_id={selectItem?.id || 0} onClose={onClose} />
</View>
}

View File

@ -4,6 +4,7 @@ import { memo, useCallback, useEffect, useState } from 'react'
import styles from './index.module.scss'
import Counter from '@/components/counter'
import LabAndImg from '@/components/LabAndImg'
import { formatHashTag } from '@/common/fotmat'
interface ProductItemParamType {
code: string
@ -11,19 +12,27 @@ interface ProductItemParamType {
name: string
}
export interface ParamItem {
export interface ColorItem {
bulk_price: number
code: string
id: number
affiliation_product: ProductItemParamType[]
color_card_name: string
texture_url: string
kind_code: string
kind_id: number
kind_name: string
lab: { l: number; a: number; b: number }
last_bulk_price: number
length_cut_price: number
name: string
rgb: { r: number; g: number; b: number }
is_add: boolean
texture_url: string
update_price_time: string
weight_cut_price: number
status: boolean
count?: number
}
export interface Param {
value: ParamItem
value: ColorItem
onChangeNum?: (val: { id: number; count: number }) => void
onDelData?: (val: number) => void
}
@ -45,7 +54,7 @@ const ProductItem = memo((props: Param) => {
}
const onMin = () => {
Taro.showModal({
title: '确认删除所选色卡',
title: '确认删除所选剪样',
success(res) {
if (res.confirm) {
props?.onDelData?.(value.id)
@ -60,7 +69,7 @@ const ProductItem = memo((props: Param) => {
<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>
<Text>{formatHashTag(value.code, value.name)}</Text>
<View className={styles.btns}>
<View className={styles.count_btn}>
<Counter

View File

@ -1,4 +1,4 @@
export default {
navigationBarTitleText: '领取色卡',
navigationBarTitleText: '领取剪样',
enableShareAppMessage: true,
}

View File

@ -4,7 +4,7 @@ import { useCallback, useMemo, useRef, useState } from 'react'
import styles from './index.module.scss'
import type { AddressItem } from './components/address'
import Address from './components/address'
import type { ParamItem } from './components/productCard'
import type { ColorItem } from './components/productCard'
import ProductCard from './components/productCard'
import Remark from './components/remark'
import { alert, goLink } from '@/common/common'
@ -12,12 +12,38 @@ import { SubmitColorCardApi } from '@/api/colorCard'
import { getFilterData } from '@/common/util'
import { UseSubscriptionMessage } from '@/use/useCommon'
import { SUBSCRIPTION_MESSAGE_SCENE } from '@/common/enum'
import { formatHashTag } from '@/common/fotmat'
export interface submitData {
address_id: number
color_card_infos: { count: number; id: number }[]
remark: string
}
export interface ParamItem {
code: string
id: number
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
component: string
craft: string
describe: string
hexadecimal_code: string
is_favorite: boolean
kind_code: string
kind_id: number
kind_name: string
name: string
product_color_count: number
product_screw_id: number
weight_density: string
width: string
colors: ColorItem[]
}
export default () => {
const submitData = useRef<submitData>({
address_id: 0,
@ -39,8 +65,8 @@ export default () => {
setAddressInfo(info.address)
setRemarkData(info.remark)
submitData.current.address_id = info?.address?.id || 0
Taro.removeStorageSync('colorCard')
Taro.removeStorageSync('colorCardOther')
// Taro.removeStorageSync('colorCard')
// Taro.removeStorageSync('colorCardOther')
})
const onAddCard = () => {
@ -51,28 +77,48 @@ export default () => {
})
}
const onDelData = useCallback((id) => {
if (list.length === 1) { return alert.none('不能删除最后一个色卡') }
const res = list?.filter((item) => {
return item.id != id
})
computeCount(res)
setList(() => res)
const onDelData = useCallback((val: ParamItem) => {
return (id: number) => {
console.log('lista:', list)
const res = val.colors?.filter((citem) => {
return citem.id != id
})
list?.map((item, index) => {
if (item.id === val.id) {
list[index] = { ...item, colors: [...res] }
}
})
// // // if (list.length === 1) { return alert.none('不能删除最后一个色卡') }
// console.log('listb:', list)
computeCount(list)
setList(() => [...list])
}
}, [list])
// 计算总数
const [numText, setNumText] = useState('')
const computeCount = (list) => {
let res = 0
list.map(item => res += item.count)
setNumText(() => `当前共 ${list.length} 种色卡, 共 ${res}`)
let p_count = 0
let c_count = 0
let all_count = 0
list?.map((item) => {
p_count += 1
item.colors?.map((citem) => {
c_count += 1
all_count += citem.count
})
})
console.log('list:::', list)
setNumText(() => `当前共 ${p_count} 种面料, ${c_count} 种色号,共 ${all_count}`)
}
const onChangeNum = useCallback((val: { id: number; count: number }) => {
list?.map((item) => {
if (item.id == val.id) {
item.count = val.count
}
item?.colors?.map((citem) => {
if (citem.id == val.id) {
citem.count = val.count
}
})
})
setList(() => list)
computeCount(list)
@ -108,14 +154,16 @@ export default () => {
return <View className={styles.main}>
<Address onSelect={getAddress} defaultValue={addressInfo} />
<View className={styles.add_card_btn} onClick={onAddCard}></View>
<View className={styles.card_con}>
<View className={styles.card_header}></View>
<View className={styles.add_card_btn} onClick={onAddCard}></View>
{list?.map(item => <View key={item.id} className={styles.card_con}>
<View className={styles.card_header}>{formatHashTag(item.code, item.name)}</View>
<View className={styles.card_list}>
{list?.map(item => <ProductCard key={item.id} value={item} onDelData={onDelData} onChangeNum={onChangeNum} />)}
{item.colors?.map(citem =>
<ProductCard key={citem.id} value={citem} onDelData={onDelData(item)} onChangeNum={onChangeNum} />,
)}
<View className={styles.express_btn}></View>
</View>
</View>
</View>)}
<Remark onSave={onRemark} defaultValue={remarkData} />
<View className={styles.order_btn}>
<View className={styles.btn_con} onClick={onSubmitData}>

View File

@ -0,0 +1,39 @@
.address_con {
display: flex;
padding: 32px;
background-color: #ffffffff;
border-radius: 16px;
.message {
display: flex;
flex-direction: column;
flex: 1;
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-dingwei" 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,32 @@
import { Text, View } from '@tarojs/components'
import Taro, { setClipboardData } from '@tarojs/taro'
import { memo } from 'react'
import styles from './index.module.scss'
import { formatDateTime } from '@/common/fotmat'
export interface OrderInfoParam {
order_no?: string
create_time?: string
}
export default memo((props: OrderInfoParam) => {
const handleCopy = () => {
setClipboardData({ data: props.order_no || '' })
}
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>{props.order_no}</Text>
<View className={styles.copy_btn} onClick={handleCopy}></View>
</View>
</View>
<View className={styles.order_info_item}>
<Text className={styles.left}></Text>
<View className={styles.right}>{formatDateTime(props.create_time)}</View>
</View>
</View>
</View>
})

View File

@ -0,0 +1,166 @@
.order_flow_state {
background-color: #fff;
border-radius: 20px;
padding: 20px;
box-sizing: border-box;
position: relative;
overflow: hidden;
margin-bottom: 20rpx;
.order_status_list {
overflow: hidden;
transition: all 0.3s ease-in-out;
.images {
display: flex;
padding: 10px 0 0 20px;
image {
width: 128px;
height: 128px;
margin-right: 10px;
}
}
}
.order_status_list_show {
max-height: 1000px !important;
}
.order_status_item {
position: relative;
&:nth-last-child(n + 2) {
padding-bottom: 30px;
}
.order_status_tail_end,
.order_status_tail {
width: 15px;
height: 15px;
border: 2px solid $color_main;
background-color: #fff;
border-radius: 50%;
position: absolute;
left: 0;
top: 10px;
z-index: 10;
}
.order_status_tail_end {
background-color: $color_main;
}
.order_status_line {
border-left: 2px solid $color_main;
height: 100%;
top: 10px;
left: 9px;
position: absolute;
z-index: 1;
}
.order_status_content {
display: flex;
align-items: center;
padding: 0 30px;
.order_status_title {
color: $color_font_two;
font-size: $font_size;
font-weight: 700;
}
.order_status_time {
color: $color_font_two;
font-size: $font_size_medium;
padding-left: 50px;
}
.order_status_tag {
font-size: $font_size_min;
background: #f0f0f0;
border-radius: 6px;
padding: 5px 10px;
color: $color_font_two;
}
.order_status_select {
color: $color_main;
}
.order_status_tag_select {
color: $color_main;
}
}
.order_status_des {
color: $color_font_two;
font-size: $font_size_medium;
padding-left: 30px;
display: inline-block;
}
.order_status_des_select {
color: $color_font_one;
}
.pay_time {
height: 56px;
background: #f6f6f6;
border-radius: 20px;
color: #3c3c3c;
font-size: 24px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
margin-top: 20px;
text {
font-size: 28px;
color: $color_main;
padding: 0 10px;
}
}
}
.more {
width: 100%;
text-align: center;
font-size: $font_size_min;
color: $color_font_one;
padding-top: 20px;
.miconfonts {
display: inline-block;
font-size: 25px;
transform: rotate(90deg);
}
.open_miconfonts {
transform: rotate(-90deg);
}
}
.image_tag {
width: 140px;
height: 144px;
.image {
width: 140px;
height: 144px;
}
position: absolute;
top: -10px;
right: -10px;
}
.refresh {
position: absolute;
top: 23px;
right: 20px;
display: flex;
color: #707070;
display: flex;
align-items: center;
.mconfont {
font-size: 30px;
}
.refresh_text {
font-size: 23px;
}
}
}
.pay_title_tag {
margin-top: 10px;
font-size: 24px;
color: #ee7500;
background: rgba(255, 230, 206, 0.36);
border-radius: 10px;
height: 56px;
display: flex;
align-items: center;
position: relative;
z-index: 999;
.miconfont {
font-size: 30px;
padding: 0 20px;
}
}

View File

@ -0,0 +1,55 @@
import { Image, Text, View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { memo } from 'react'
import classnames from 'classnames'
import styles from './index.module.scss'
import { formatDateTime, formatImgUrl } from '@/common/fotmat'
export interface orderStateItem {
audit_remark: string
audit_time: string
delivery_appendix_url: string[]
order_status: number
order_status_name: string
}
export interface orderStateParam {
onRefresh?: () => void
list?: orderStateItem[]
}
const OrderState = (props: orderStateParam) => {
const { list = [] } = props
const onShowImage = (url: string, list: string[]) => {
Taro.previewImage({
current: formatImgUrl(url, '!w800'),
urls: formatImages(list),
})
}
const formatImages = (list: string[]) => {
return list?.map(item => formatImgUrl(item, '!w800'))
}
return (
<>
<View className={styles.order_flow_state}>
<View className={classnames(styles.order_status_list)}>
{list?.map((item, index) => <View className={styles.order_status_item} key={index}>
{(list?.length > 1) && <View className={classnames(styles.order_status_tail, (index == 0) && styles.order_status_tail_end)}></View>}
{(list?.length != (index + 1)) && <View className={styles.order_status_line}></View>}
<View className={styles.order_status_content}>
<View className={classnames(styles.order_status_title, (index == 0) && styles.order_status_select)}>{item.order_status_name}</View>
<View className={classnames(styles.order_status_time, (index == 0) && styles.order_status_select)}>{formatDateTime(item.audit_time)}</View>
</View>
<Text className={classnames(styles.order_status_des, (index == 0) && styles.order_status_des_select)}>{item.audit_remark}</Text>
{item.delivery_appendix_url?.length > 0 && <View className={styles.images}>
{item.delivery_appendix_url?.map((citem, index) => {
return <View key={index} onClick={() => onShowImage(citem, item.delivery_appendix_url)}><Image src={formatImgUrl(citem, '!w400')} ></Image></View>
})}
</View>}
</View>)}
</View>
</View>
</>
)
}
export default memo(OrderState)

View File

@ -0,0 +1,60 @@
.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);
display: flex;
justify-content: space-between;
width: 100%;
text {
&:nth-child(1) {
flex: 1;
@include common_ellipsis();
}
}
.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,45 @@
import { Text, View } from '@tarojs/components'
import { useCallback } from 'react'
import styles from './index.module.scss'
import Counter from '@/components/counter'
import LabAndImg from '@/components/LabAndImg'
export interface orderParam {
affiliation_product: any
count: number
lab: { l: number; a: number; b: number }
name: string
rgb: { r: number; g: number; b: number }
texture_url: string
}
interface Param {
value: orderParam[]
}
export default (props: Param) => {
const { value } = props
const labAndImgObj = useCallback(
(item) => {
return { lab: item.lab, rgb: item.rgb, texture_url: item.texture_url }
},
[value],
)
return <View className={styles.card_con}>
<View className={styles.card_header}></View>
<View className={styles.card_list}>
<>
{value?.map((item, index) => {
return <View key={index} className={styles.card_item}>
<View className={styles.img}><LabAndImg value={labAndImgObj(item)} /></View>
<View className={styles.name_count}>
<Text>{item.name}</Text>
<Text>x{item.count}</Text>
</View>
</View>
})}
<View className={styles.express_btn}></View>
</>
</View>
</View>
}

View File

@ -0,0 +1,26 @@
.remarks {
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 {
padding: 20px 0;
color: rgba(0, 0, 0, 0.4);
}
.valuable {
color: rgba(0, 0, 0, 0.8);
}
}

View File

@ -0,0 +1,23 @@
import { Input, Text, View } from '@tarojs/components'
import { useState } from 'react'
import classNames from 'classnames'
import styles from './index.module.scss'
import Remark from '@/components/remark'
interface Param {
value: string
placeholder: 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 className={classNames(props.value ? styles.valuable : '')}>{props.value || props.placeholder}</Text>
</View>
</View>
</>
}

View File

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

View File

@ -0,0 +1,46 @@
.main {
min-height: 100vh;
background-color: #f7f7f7ff;
padding: 24px;
padding-bottom: 180px;
.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,96 @@
import { Text, View } from '@tarojs/components'
import Taro, { useDidShow, useRouter } from '@tarojs/taro'
import { useMemo, useState } from 'react'
import styles from './index.module.scss'
import Address from './components/address'
import type { orderParam } from './components/productCard'
import ProductCard from './components/productCard'
import Remark from './components/remark'
import OrderInfo from './components/orderInfo'
import type { orderStateItem } from './components/orderState'
import OrderState from './components/orderState'
import { alert, goLink } from '@/common/common'
import SearchInput from '@/components/searchInput'
import { ColorCardOrderCancelApi, GetColorCardOrderDetailApi } from '@/api/colorCard'
interface Param {
address: string
color_card_info: orderParam[]
create_time: string
create_user_name: string
creator_id: number
id: number
order_no: string
order_progress: orderStateItem[]
order_status: number
order_status_name: string
purchaser_id: number
purchaser_name: string
purchaser_phone: string
remark: string
sale_user_id: number
sale_user_name: string
shipment_mode: number
shipment_mode_name: string
target_user_name: string
target_user_phone: string
update_time: string
update_user_name: string
updater_id: number
}
export default () => {
const router = useRouter()
const [orderData, setOrderData] = useState<Param>()
const { fetchData: fetchDataDtail } = GetColorCardOrderDetailApi()
const getColorCardOrderDetail = async() => {
const res = await fetchDataDtail({ id: router.params.id })
setOrderData(() => res.data)
}
useDidShow(() => {
getColorCardOrderDetail()
})
const addressData = useMemo(() => {
return {
address_title: orderData?.address || '',
address_name: orderData?.purchaser_name || '',
address_phone: orderData?.purchaser_phone || '',
address_mode: orderData?.shipment_mode_name || '',
}
}, [orderData])
// 取消订单
const { fetchData: fetchDataCancel } = ColorCardOrderCancelApi()
const onCancel = async() => {
Taro.showModal({
title: '确定取消订单?',
async success(res) {
if (res.confirm) {
const res = await fetchDataCancel({ id: orderData?.id })
if (res.success) {
alert.success('取消成功')
getColorCardOrderDetail()
}
}
else if (res.cancel) {
console.log('用户点击取消')
}
},
})
}
return <View className={styles.main}>
<OrderState list={orderData?.order_progress} />
<Address defaultValue={addressData} />
<ProductCard value={orderData?.color_card_info || []} />
<OrderInfo {...orderData} />
<Remark value={orderData?.remark || ''} placeholder="尚未备注信息" />
{orderData?.order_status === 1 && <View className={styles.order_btn}>
<View className={styles.btn_con}>
<View className={styles.btn} onClick={onCancel}></View>
</View>
</View>}
</View>
}