✨ feat(颜色取样|取色查找|样品对比): 移植内部版相关功能

This commit is contained in:
xuan
2022-09-14 13:22:56 +08:00
parent 48e5986060
commit 03e7377485
54 changed files with 2353 additions and 458 deletions
@@ -5,7 +5,7 @@ import { useBluetooth } from '@/use/contextBlueTooth'
import SearchInput from '@/components/searchInput'
import Popup from './Popup'
import classnames from 'classnames'
import styles from '../../css/linkBlueTooth.module.scss'
import styles from '../css/linkBlueTooth.module.scss'
export default memo(() => {
const { state, init, startScan, connect, disconnect } = useBluetooth()
@@ -1,7 +1,7 @@
import { ScrollView, View } from '@tarojs/components'
import { memo, useEffect, useState } from 'react'
import Loading from '@/components/loading'
import style from '../../css/popup.module.scss'
import style from '../css/popup.module.scss'
interface params {
state: any
@@ -1,10 +1,7 @@
.main {
width: 690px;
height: 86px;
width: 100%;
background: #ffffff;
border-radius: 10px;
margin-top: 24px;
margin-left: 30px;
.bluetooth_link {
display: flex;
@@ -39,4 +36,4 @@
color: #f0ec09;
}
}
}
}
@@ -0,0 +1,46 @@
.popups {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
.cover {
position: fixed;
height: 100vh;
width: 100vw;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 10;
}
.popcoms {
z-index: 100;
position: fixed;
top: 50%;
left: 50%;
border-radius: 20px;
transform: translateX(-50%) translateY(-50%);
.con {
width: 500px;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.showRgb {
width: 100%;
height: 550px;
background-color: #fff;
border-radius: 20px;
}
.name {
width: 100%;
text-align: center;
color: #fff;
padding: 20px 0;
font-size: 26px;
background: rgba(0, 0, 0, 0.5);
border-radius: 20px;
}
}
}
@@ -0,0 +1,30 @@
import { View } from "@tarojs/components"
import React, { FC, memo, useEffect, useState } from "react"
import styles from './index.module.scss'
type PropsType = {
showModal: boolean
children?: React.ReactNode
}
const DrawerCenter: FC<PropsType> = memo((props) => {
const { children, showModal } = props
const [show, setShow] = useState(false)
useEffect(() => {
setShow(showModal)
}, [showModal])
// 关闭
const close = () => {
setShow(false)
}
return show ? (
<View className={styles.popups} catchMove>
<View className={styles.popcoms}>{children}</View>
<View className={styles.cover} onClick={close}></View>
</View>
) : null
})
export default DrawerCenter
@@ -0,0 +1,113 @@
.history_color {
.selectCon {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
.selectList {
width: 692px;
height: 230px;
background: #ffffff;
border-radius: 30px;
margin-bottom: 20px;
display: flex;
align-items: center;
padding: 20px 0;
box-sizing: border-box;
.rgbColor {
width: 161px;
height: 161px;
background: red;
border-radius: 50%;
margin-left: 30px;
box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.6);
}
.product_con {
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 32px;
font-size: 26px;
height: 100%;
width: 300px;
color: #505050;
.product_name {
@include common_ellipsis();
font-size: 28px;
color: #5f5f5f;
font-weight: 700;
margin-bottom: 46px;
}
.product_color {
@include common_ellipsis();
margin-bottom: 15px;
}
.contrast {
display: flex;
margin-bottom: 20px;
.g_num {
@include common_ellipsis();
}
.num {
color: #00499f;
background: #c9e4ff;
padding: 3px 10px;
border-radius: 7px;
margin-left: 18px;
}
}
.date {
background: rgba(0, 0, 0, 0.3);
color: #fff;
padding: 3px 10px;
border-radius: 10px;
width: 258px;
}
}
.labColor {
flex: 1;
// height: 100%;
display: flex;
flex-direction: column;
align-items: center;
font-size: 27px;
color: #707070;
.labColor_btn {
width: 47px;
height: 47px;
background: #007aff;
color: #fff;
text-align: center;
line-height: 47px;
border-radius: 50%;
font-size: 39px;
margin-bottom: 20px;
}
.labColor_con {
flex: 1;
.L,
.a {
margin-bottom: 10px;
}
}
}
}
.noData {
display: flex;
justify-content: center;
align-items: center;
color: #707070;
height: 100%;
width: 100%;
font-size: 26px;
}
}
.selectList-scroll-color {
height: 70vh;
width: 100%;
}
.drawer-container {
background: #f0f0f0;
}
}
@@ -0,0 +1,89 @@
import Popup from "@/components/popup"
import { ScrollView, View } from "@tarojs/components"
import { FC, useEffect, useState } from "react"
import styles from './index.module.scss'
import { formatDateTime} from "@/common/format";
import {toRgb} from '@/common/bluetooth/color/colorSpace'
import Taro from "@tarojs/taro";
type PropsType = {
showModal: boolean
onColor?:Function
}
const HistoryColor: FC<PropsType> = (props) => {
const { onColor, showModal } = props
const [show, setShow] = useState(false)
useEffect(() => {
setShow(showModal)
}, [showModal])
const closeEven = () => {
setShow(false)
}
const [list, setList] = useState([
{
p_time: 0,
lab: [],
code: '',
name: ''
}
])
//保留1位小数
const noScale = (val, num = 1) => {
return val?.toFixed(num)
}
//rgb转换字符串
const labRoRgb = (val) => {
const rgb = toRgb(val)
return `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`
}
const getInfo = (item) => {
onColor && onColor(item)
}
return (
<View className={styles.history_color}>
<Popup title='历史取样记录 ( 最近30条 )' show={show} onClose={closeEven}>
<ScrollView className={styles['selectList-scroll-color']} scrollY>
<View className={styles.selectCon}>
{!!list?.length ? (
list.map((item, index) => {
return (
<View key={item.p_time} className={styles.selectList} onClick={() => getInfo(item)}>
<View className={styles.rgbColor} style={{ background: labRoRgb(item.lab) }}></View>
<View className={styles.product_con}>
<View className={styles.product_name}>{item.code + ' ' + item.name}</View>
<View className={styles.date}>{formatDateTime(item.p_time)}</View>
</View>
<View className={styles.labColor}>
<View className={styles.labColor_btn}>+</View>
<View className={styles.labColor_con}>
<View className={styles.L}>L*:{noScale(item.lab[0])}</View>
<View className={styles.a}>a*:{noScale(item.lab[1])}</View>
<View className={styles.b}>b*:{noScale(item.lab[2])}</View>
</View>
</View>
</View>
)
})
) : (
<View className='noData'>暂无数据</View>
)}
</View>
</ScrollView>
</Popup>
</View>
)
}
export default HistoryColor
@@ -0,0 +1,46 @@
.lab_color_main {
display: flex;
justify-content: space-between;
padding: 20px 0;
font-size: 28px;
.btnColor {
width: 264px;
height: 264px;
background: #dddddd;
border-radius: 50%;
text-align: center;
line-height: 264px;
color: #707070;
box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.6);
}
.labCon {
display: flex;
flex-direction: column;
justify-content: center;
padding: 20px 0 20px 20px;
color: #707070;
.lab {
color: #707070;
display: flex;
margin-bottom: 20px;
text {
display: flex;
&:nth-child(1) {
font-weight: 700;
}
&:nth-child(n + 2) {
background-color: #fff;
margin-left: 17px;
padding: 3px 15px;
border-radius: 10px;
width: 73px;
display: flex;
justify-content: center;
}
}
}
.date {
font-size: 26px;
}
}
}
@@ -0,0 +1,54 @@
import { View, Text } from '@tarojs/components'
import { FC, useMemo } from 'react'
import { toRgb } from '@/common/bluetooth/color/colorSpace'
import styles from './index.module.scss'
import { formatDateTime } from '@/common/format'
type PropsType = {
lab?: Array<any>
time?: any
onLab?: Function
}
const LabColor: FC<PropsType> = (props) => {
const { lab = [], time, onLab } = props
const noScale = (val, num = 1) => {
return val.toFixed(num)
}
const labObj = useMemo(() => {
if (lab.length <= 0) return { lab: [], rgb: '' }
const rgb = toRgb(lab)
return {
lab: [noScale(lab[0]), noScale(lab[1]), noScale(lab[2])],
rgb: `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`,
}
}, [lab])
const labTime = useMemo(() => {
if (time.length <= 0) return ''
return formatDateTime(time)
}, [time])
const onLabEven = () => {
onLab && onLab()
}
return (
<View className={styles.lab_color_main}>
<View className={styles.btnColor} onClick={onLabEven} style={{ background: labObj.rgb }}>
{!!labObj.lab.length ? '' : '点击取色'}
</View>
<View className={styles.labCon}>
<View className={styles.lab}>
<Text>L*a*b*:</Text>
<Text>{labObj.lab[0]}</Text>
<Text>{labObj.lab[1]}</Text>
<Text>{labObj.lab[2]}</Text>
</View>
<View className={styles.date}>{labTime && <Text>取样时间: {labTime}</Text>}</View>
</View>
</View>
)
}
export default LabColor
@@ -0,0 +1,121 @@
.RecommendColor_main {
width: 100%;
.RecommendColor_list {
display: flex;
flex-wrap: wrap;
.RecommendColor_item {
background: #fff;
width: 48.5%;
height: 356px;
border-radius: 30px;
margin-bottom: 20px;
&:nth-child(2n) {
margin-left: 3%;
}
.rgbColor {
width: 100%;
height: 188px;
background: rgb(0, 195, 255);
border-radius: 30px 30px 0 0;
position: relative;
.lab {
width: 90px;
height: 100%;
background: rgba(0, 0, 0, 0.3);
position: absolute;
right: 0;
top: 0;
border-radius: 0 30px 0 0;
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 26px;
text {
&:nth-child(1) {
font-weight: 700;
margin-bottom: 10px;
}
}
}
}
.product_con {
display: flex;
flex-direction: column;
font-size: 26px;
padding: 10px 15px 15px 15px;
box-sizing: border-box;
.product_color {
color: #505050;
@include common_ellipsis();
}
.product_title {
display: flex;
justify-content: space-between;
.product_name {
@include common_ellipsis();
color: #0c68c5;
font-weight: 700;
font-size: 28px;
flex: 1;
margin-right: 10px;
}
.product_num {
background: #c9e4ff;
color: #00499f;
padding: 3px 6px;
font-size: 26px;
border-radius: 5px;
margin-bottom: 13px;
}
}
.date {
margin-top: 15px;
color: #808080;
display: flex;
align-items: center;
justify-content: space-between;
.labColor_btn {
width: 47px;
height: 47px;
background: #007aff;
color: #fff;
text-align: center;
line-height: 47px;
border-radius: 50%;
font-size: 39px;
margin-right: 10px;
}
.g_num {
flex: 1;
margin-right: 10px;
@include common_ellipsis();
}
}
}
}
}
.con {
width: 500px;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
.showRgb {
width: 100%;
height: 550px;
background-color: #fff;
border-radius: 20px;
}
.name {
width: 100%;
text-align: center;
color: #fff;
padding: 20px 0;
font-size: 26px;
background: rgba(0, 0, 0, 0.5);
border-radius: 20px;
}
}
}
@@ -0,0 +1,83 @@
import { FC, useState } from 'react'
import { View, Text } from '@tarojs/components'
import { toRgb } from '@/common/bluetooth/color/colorSpace'
import styles from './index.module.scss'
import { formatDateTime } from '@/common/format'
import classnames from 'classnames'
import DrawerCenter from '../DrawerCenter'
type PropsType = {
list?: Array<any>
customStyle?: React.CSSProperties
}
const RecommendColor: FC<PropsType> = (props) => {
const { list, customStyle = {} } = props
//rgb转换字符串
const labRoRgb = (val) => {
const lab = val ? [val.l, val.a, val.b] : []
const rgb = toRgb(lab)
return `rgb(${rgb[0]},${rgb[1]},${rgb[2]})`
}
//保留1位小数
const noScale = (val, num = 1) => {
return val.toFixed(num)
}
const [show, setShow] = useState(false)
const [selectObj, setSelectObj] = useState({
rgb: '',
product_color_code: '',
product_color_name: ''
})
const openShow = (val) => {
setShow(true)
setSelectObj(val)
setSelectObj({ ...val, rgb: labRoRgb(val.lab) })
}
return (
<View className={classnames(styles.RecommendColor_main, customStyle)}>
<View className={styles.RecommendColor_list}>
{list?.map((item) => {
return (
<View className={styles.RecommendColor_item} key={item.id} onClick={() => openShow(item)}>
<View className={styles.rgbColor} style={{ background: labRoRgb(item.lab) }}>
<View className={styles.lab}>
<text>L*a*b*</text>
<text>{noScale(item.lab.l)}</text>
<text>{noScale(item.lab.a)}</text>
<text>{noScale(item.lab.b)}</text>
</View>
</View>
<View className={styles.product_con}>
<View className={styles.product_title}>
<View className={styles.product_name}>{item.product_code + '# ' + item.product_name}</View>
<View className={styles.product_num}>{noScale(item.match_rate_percent, 1)}%</View>
</View>
<View className={styles.product_color}>{item.product_color_code + ' ' + item.product_color_name}</View>
<View className={styles.date}>
<text className={styles.g_num}>{item.dyelot_number}</text>
<View className={styles.labColor_btn}>+</View>
</View>
</View>
</View>
)
})}
</View>
<DrawerCenter showModal={show}>
<View className={styles.con}>
<View className={styles.showRgb} style={{ background: selectObj?.rgb }}></View>
<View className={styles.name}>{selectObj.product_color_code + ' ' + selectObj.product_color_name}</View>
</View>
</DrawerCenter>
</View>
)
}
export default RecommendColor
@@ -0,0 +1,4 @@
export default {
navigationBarTitleText: '取色查找',
enableShareAppMessage: false,
}
@@ -0,0 +1,94 @@
page {
height: 100vh;
}
.findColor_main {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
min-height: 100%;
background: #f3f3f3;
box-sizing: border-box;
.findColor_main_search {
background: #fff;
width: 100%;
padding: 0 20rpx;
border-radius: 20rpx;
box-sizing: border-box;
}
.findColor_main_title {
width: 100%;
.RecommendColor_title {
display: flex;
justify-content: space-between;
font-size: 28px;
margin-bottom: 20px;
padding: 10px 20px;
box-sizing: border-box;
color: #707070;
font-weight: bold;
border-bottom: 1px dashed #e4e4e4;
width: 100%;
text {
&:nth-child(2) {
color: #007aff;
}
}
}
}
.noList {
flex: 1;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
color: #707070;
font-size: 26px;
}
.list {
display: flex;
padding: 20px;
box-sizing: border-box;
border: 1px solid #ccc;
width: 100%;
justify-content: space-between;
border-radius: 10px;
font-size: 25px;
margin-top: 20px;
}
.measure {
width: 100%;
.list {
justify-content: center;
}
.content {
width: 100%;
}
.diff {
text-align: center;
}
}
.color {
margin-top: 20px;
}
.labAndRgb {
display: flex;
width: 100%;
justify-content: center;
margin-top: 30px;
.item {
margin-top: 20px;
font-size: 28px;
}
}
.color_list {
margin-top: 30px;
margin-bottom: 30px;
display: flex;
justify-content: center;
.color_item {
width: 250px;
height: 250px;
}
}
}
+140
View File
@@ -0,0 +1,140 @@
import { View, Text } from '@tarojs/components'
import { FC, useEffect, useState } from 'react'
import styles from './index.module.scss'
import LineBluetooth from '../components/bluetooth/LinkBlueTooth'
import HistoryColor from './components/HistoryColor'
import LabColor from './components/LabColor'
import SelectProduct from '@/components/selectProduct'
import { useBluetooth } from '@/use/contextBlueTooth'
import RecommendColor from './components/RecommendColor'
import { FindColorListApi } from '@/api/index'
import Loading from '@/components/loading'
import Taro from '@tarojs/taro'
import { throttle } from '@/common/util'
const FindColor: FC = () => {
const { measureAndGetLab, disconnect, connected, deviceLab } = useBluetooth()
const { state: colorState, fetchData: ApiFindColorList } = FindColorListApi()
const [list, setList] = useState([])
const [product, setProduct] = useState<Record<string, any>>({})
//获取数据
const getData = async () => {
setList([])
await ApiFindColorList({
product_id: product.id,
l: labArray[0],
a: labArray[1],
b: labArray[2],
})
setList(colorState.data.list)
}
const [labArray, setlabArray] = useState<Array<any>>([])
const [labtime, setLabtime] = useState<any>(+new Date())
//点击获取lab按钮
const labEven = throttle(async () => {
if (!connected) {
Taro.showToast({ title: '请先链接设备', icon: 'none' })
return
}
if (!product) {
Taro.showToast({ title: '请选择面料', icon: 'none' })
return
}
await measureAndGetLab()
}, 500)
const selectInput = (val) => {
setProduct(val)
setLabtime('')
setlabArray([])
setList([])
}
const getColor = (val) => {
setList([])
setlabArray(val.lab)
setLabtime(val.p_time)
setProduct({
code: val.code,
default: val.default,
id: val.id,
name: val.name,
})
getData()
}
const [listLoading, setListLoading] = useState(false)
useEffect(() => {
setListLoading(colorState.loading)
}, [colorState])
const [showHistory, setShowHistory] = useState(false)
const ResultContainer = () => {
if (!listLoading && list?.length > 0) {
return <RecommendColor customStyle={{ flex: 1 }} list={list} />
} else if (!listLoading && labArray.length == 0) {
return <View className={styles.noList}>-请取色-</View>
} else if (!listLoading && labArray.length > 0 && list?.length == 0) {
return <View className={styles.noList}>-暂无数据-</View>
} else if (listLoading) {
return <Loading />
}
}
//历史取样
const historyShowEven = () => {
setShowHistory(true)
}
useEffect(() => {
if (!product) {
Taro.showToast({ title: '请选择面料', icon: 'none' })
return
}
if (deviceLab) {
setLabtime(+new Date())
setlabArray([deviceLab.L, deviceLab.a, deviceLab.b])
// console.log('state.labArray::',state.labArray)
localSave()
getData()
}
}, [deviceLab])
//本地存储取色记录(无差别存储版本)
const localSave = () => {
let historyColorList = Taro.getStorageSync('historyColor') || []
let obj = {
...product,
p_time: labtime,
lab: labArray,
}
historyColorList.unshift(obj)
if (historyColorList.length > 30) historyColorList.pop()
Taro.setStorageSync('historyColor', historyColorList)
}
return (
<View className={styles.findColor_main}>
<View className={styles.findColor_main_search}>
<LineBluetooth></LineBluetooth>
<SelectProduct selectColorId={product?.id} noAll={true} onSelect={selectInput} />
</View>
<LabColor lab={labArray} time={labtime} onLab={labEven} />
<View className={styles.findColor_main_title}>
<View className={styles.RecommendColor_title}>
<Text>推荐数 ({list?.length})</Text>
<Text onClick={historyShowEven}>历史取样</Text>
</View>
</View>
<HistoryColor showModal={showHistory} onColor={getColor} />
{ResultContainer()}
<View className='common_safe_area_y'></View>
</View>
)
}
export default FindColor
@@ -1,10 +1,10 @@
import { Image, Text, Textarea, View } from '@tarojs/components'
import Taro, { useDidShow, usePullDownRefresh, useRouter } from '@tarojs/taro'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useBluetooth } from '../../use/contextBlueTooth'
import { useBluetooth } from '@/use/contextBlueTooth'
import classnames from 'classnames'
import LinkBlueTooth from './compoents/bluetooth/LinkBlueTooth'
import { toRgb } from '../../common/bluetooth/color/colorSpace'
import LinkBlueTooth from '../components/bluetooth/LinkBlueTooth'
import { toRgb } from '@/common/bluetooth/color/colorSpace'
import styles from './index.module.scss'
import { productabsorbcontrast } from '@/api/index'
export default () => {
@@ -119,16 +119,9 @@ export default () => {
}
return (
<View className={styles.body}>
{/* <View className={styles.topBox}>
<View className={styles.leftBox}>
<View className={styles.leftFont}>蓝牙设备</View>
<View className={styles.borderBox}></View>
<View className={styles.cricleBox}></View>
<View className={styles.notNet}></View>
</View>
<Text className={classnames("iconfont icon-a-moreback", styles.iconMore)}></Text>
</View> */}
<LinkBlueTooth />
<View className={styles.topBox}>
<LinkBlueTooth />
</View>
<View className={styles.contBox}>
<View className={styles.firstBox} style='margin-right:27px'>
<View className={styles.firstLeftName}>基础样品</View>
@@ -0,0 +1,184 @@
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
@mixin flex-vertical-center {
display: flex;
align-items: center;
}
@mixin ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
display: inline-block;
}
.color-list {
@include flex-vertical-center;
justify-content: space-between;
width: 690px;
background: #ffffff;
opacity: 1;
padding: 30px;
box-sizing: border-box;
margin: 20px auto 0;
border-radius: 35px;
z-index: 0;
position: relative;
border: 4px solid transparent;
}
.vertical {
position: absolute;
width: 0;
height: 105%;
z-index: -1;
overflow: hidden;
top: 50%;
left: 50%;
border-radius: 35px;
transform: translate(-50%, -50%);
}
.vertical view {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 690px;
height: 95%;
border-radius: 35px;
border: 4px solid #007aff;
// border-bottom: 3px solid #007AFF;
}
.move-vertical {
width: 700px;
animation: moveVertical 0.3s ease;
}
@keyframes moveVertical {
from {
width: 0;
}
to {
width: 700px;
}
}
.horizontal {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
overflow: hidden;
top: 50%;
left: 50%;
border-radius: 35px;
transform: translate(-50%, -50%);
}
.move-horizontal {
height: 0;
animation: moveHorizontal 0.3s ease 0.3s;
}
@keyframes moveHorizontal {
from {
height: 100%;
}
to {
height: 0;
}
}
.flash {
animation-name: KFlash;
animation-duration: 0.5s;
animation-timing-function: linear;
animation-direction: alternate;
animation-iteration-count: infinite;
}
@keyframes KFlash {
to {
border: 4px solid #999;
}
}
.c-image {
width: 161px;
height: 161px;
background: rgba(0, 0, 0, 0);
overflow: hidden;
border-radius: 50%;
position: relative;
}
.c-image text {
font-size: 25px;
color: white;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.c-image image {
width: 100%;
height: 100%;
}
.c-info {
width: 296px;
margin-left: 25px;
margin-right: 25px;
overflow: hidden;
line-height: 34px;
}
.c-info text {
@include ellipsis;
width: 100%;
font-size: 26px;
font-weight: 400;
line-height: 34px;
color: #707070;
}
.c-i-title {
@include ellipsis;
width: 100%;
font-size: 28px;
font-weight: bold;
line-height: 38px;
color: #707070;
margin: 5px 0;
}
.c-i-date {
@include flex-center;
width: 268px;
height: 38px;
background: rgba(0, 0, 0, 0.3);
border-radius: 6px;
font-size: 24px;
font-weight: 400;
color: #ffffff;
margin-top: 17px;
}
.c-lab {
height: 100%;
justify-self: flex-end;
@include flex-vertical-center;
flex-direction: column;
}
.c-lab .c-lab-button {
@include flex-center;
height: 48px;
min-width: 96px;
background: #007aff;
border-radius: 50px;
font-size: 24px;
font-weight: 400;
line-height: 32px;
color: #ffffff;
margin-bottom: 12px;
padding: 0 15px;
}
.c-lab .c-lab-button.again {
background: #f0f0f0;
color: #007aff;
}
.c-lab .c-lab-text {
font-size: 24px;
font-weight: 400;
line-height: 36px;
color: #707070;
margin-top: 25px;
}
@@ -0,0 +1,78 @@
import { View, Text } from '@tarojs/components'
import React, { FC } from 'react'
import classnames from 'classnames'
import styles from './index.module.scss'
import { formatHashTag } from '@/common/format'
import dayjs from 'dayjs'
type PropsType = {
item?: Record<string, any>
key?: any
index?: number
onPreviewRgb?: Function
onTakeColor?: Function
}
const ColorCard: FC<PropsType> = (params) => {
const { item = {}, index, onTakeColor, onPreviewRgb, key } = params
const truncation = (ev) => {
if (ev) {
ev += ''
let index = ev.lastIndexOf('.')
let suffix = ev.substr(index + 1)
if (suffix.length > 2) {
suffix = suffix.substr(0, 1)
ev = ev.substr(0, index) + '.' + suffix
}
return ev
} else {
return 0
}
}
const handleTakeColor = () => {
onTakeColor && onTakeColor(index)
}
const handlePreviewRgb = () => {
onPreviewRgb && onPreviewRgb()
}
return (
<View className={classnames(styles['color-list'], { flash: item.moveBorder == 1 })} key={key}>
<View className={classnames(styles.vertical, { 'move-vertical': item.moveBorder == 2 })}>
<View></View>
</View>
<View className={classnames(styles.horizontal, { 'move-horizontal': item.moveBorder == 2 })}></View>
<View
onClick={handlePreviewRgb}
className={styles['c-image']}
style={{
backgroundColor: `rgb(
${item.currnetRgb?.r},
${item.currnetRgb?.g},
${item.currnetRgb?.b}
)`,
}}>
{!item.sampling && <Text>末取样</Text>}
</View>
<View className={styles['c-info']}>
<View className={styles['c-i-title']}>{formatHashTag(item.product_code, item.product_name)}</View>
<Text>{formatHashTag(item.product_color_code, item.product_color_name)}</Text>
<View className={styles['c-i-date']}>{item.absorb_lab_time && dayjs(item.absorb_lab_time).format('YYYY-MM-DD HH:mm:ss')}</View>
</View>
<View className={styles['c-lab']}>
<View className={classnames(styles['c-lab-button'], { again: item.sampling })} onClick={handleTakeColor}>
{item.sampling ? '重新取样' : '取样'}
</View>
<View className={styles['c-lab-text']}>
<View>L*: {truncation(item?.currentLab?.l)}</View>
<View>a*: {truncation(item?.currentLab?.a)}</View>
<View>b*: {truncation(item?.currentLab?.b)}</View>
</View>
</View>
</View>
)
}
export default ColorCard
@@ -0,0 +1,68 @@
@mixin flex-center{
display: flex;
justify-content: center;
align-items: center;
}
@mixin flex-vertical-center{
display: flex;
align-items: center;
}
.tc-info{
@include flex-vertical-center;
justify-content: space-between;
margin: 15px 30px;
}
.tc-i-upload{
width: 264px;
height: 264px;
background: #DDDDDD;
border-radius: 264px;
position: relative;
z-index: 1;
overflow: hidden;
}
.tc-i-upload image{
width: 100%;
height: 100%;
}
.tc-i-u-box{
@include flex-center;
flex-direction: column;
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
color: #707070;
font-size: 26px;
}
.tc-i-u-box text{
margin-bottom: 15px;
font-size: 50px;
}
.tc-i-num{
@include flex-vertical-center;
font-size: 44px;
font-weight: 400;
line-height: 58px;
}
.tc-i-num>view{
padding: 0 48px;
position: relative;
text-align: center;
}
.tc-i-num>view:first-child::after{
content: " ";
width: 0px;
height: 64px;
border: 2px solid #DDDDDD;
position: absolute;
right: 0;top: 50%;
transform: translateY(-50%);
}
.tc-i-num text{
font-size: 26px;
font-weight: 400;
line-height: 34px;
color: #707070;
}
@@ -0,0 +1,48 @@
import { View, Text,Image } from '@tarojs/components'
import styles from './index.module.scss'
import classnames from 'classnames'
import { FC, useRef, useState } from "react"
import Upload from '../Upload'
import {screenshot} from '@/common/util'
type PropsType = {
onUploadConfirm?: Function
}
const Texture:FC<PropsType> = (params) => {
const {onUploadConfirm} = params
const handleUploadConfirm = () => {
onUploadConfirm && onUploadConfirm()
}
const uploadEl = useRef()
return (
<View className={styles['texture-container']}>
<View className={styles['tc-info']}>
<View onClick={uploadEl.handleTriggerUploadModal(true)} className={styles['tc-i-upload']}>
{detail.texture_url && <Image src={screenshot(detail.texture_url)} />}
<View v-else className='tc-i-u-box'>
<Text className='iconfont icon-shangchuanzhaopian'></Text>
<View>上传纹理</View>
</View>
</View>
<View className={styles['tc-i-num']}>
<View>
<View className='color-blue'>{(data?.list?.length ?? 0) - calcNoSampling}</View>
<Text>已取样</Text>
</View>
<View>
<View className='color-yellow'>{calcNoSampling}</View>
<Text>未取样</Text>
</View>
</View>
</View>
<Upload onUploadConfirm={handleUploadConfirm} ref={uploadEl} />
</View>
)
}
export default Texture
@@ -0,0 +1,68 @@
@mixin flex-center{
display: flex;
justify-content: center;
align-items: center;
}
@mixin flex-vertical-center{
display: flex;
align-items: center;
}
.upload-container .drawer{
position: fixed;
top: 0;
z-index: 10;
}
.u-content{
@include flex-center;
flex-direction: column;
width: 100%;
padding: 65px 0;
}
.u-image{
width: 422px;
height: 422px;
background: #F0F0F0;
border-radius: 50%;
overflow: hidden;
position: relative;
z-index: 0;
}
.u-image view{
width: 100%;
height: 100%;
@include flex-center;
font-size: 28px;
font-weight: 400;
color: #707070;
position: absolute;
top: 0;left: 0;
z-index: 1;
}
.u-image .update-statu{
color: white;
background-color: rgba(0, 0, 0, 0.5);
}
.u-image image{
width: 100%;
height: 100%;
}
.u-button{
display: flex;
margin-top: 76px;
}
.u-button view{
width: 264px;
height: 82px;
background: #F0F0F0;
border-radius: 82px;
@include flex-center;
font-size: 32px;
font-weight: 400;
color: #007AFF;
margin: 0 15px;
}
.u-button .confirm{
background: #007AFF;
color: white;
}
@@ -0,0 +1,62 @@
import Popup from "@/components/popup"
import { FC, useState } from "react"
import { View, Text,Image } from '@tarojs/components'
import styles from './index.module.scss'
import classnames from 'classnames'
import Taro from "@tarojs/taro"
type PropsType = {
onUploadConfirm?: Function
}
const UploadColor: FC<PropsType> = (params) => {
const { onUploadConfirm } = params
const [showModal, setShowModal] = useState(false)
const [filePath, setFilePath] = useState('')
const [file, setFile] = useState({})
const handleUpload = async () => {
Taro.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album'],
success(ev) {
setFilePath(ev.tempFiles[0].tempFilePath)
setFile(ev.tempFiles[0])
},
})
}
const handleTriggerUploadModal = (bool: boolean) => {
setShowModal(bool)
}
const handleClear = () => {
setFilePath('')
}
const handleUploadConfirm = () => {
onUploadConfirm && onUploadConfirm(file)
}
return (
<View className={styles['upload-container']}>
<Popup title='上传纹理' show={showModal} onClose={() => handleTriggerUploadModal(false)}>
<View className={styles['u-content']}>
<View onClick={handleUpload} className={styles['u-image']}>
{filePath && <Image mode='aspectFill' src={filePath} />}
<View className={classnames({ 'update-statu': filePath })}>{filePath ? '点击修改' : '点击上传'}</View>
</View>
<View className={styles['u-button']}>
<View onClick={handleClear}>清除</View>
<View onClick={handleUploadConfirm} className={styles.confirm}>
确定
</View>
</View>
</View>
</Popup>
</View>
)
}
export default UploadColor
@@ -0,0 +1,4 @@
export default {
navigationBarTitleText: '颜色取样',
enableShareAppMessage: false,
}
@@ -0,0 +1,148 @@
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
@mixin flex-vertical-center {
display: flex;
align-items: center;
}
page {
background: #f3f3f3;
}
.card {
background: #fff;
padding: 0 20px;
border-radius: 20px;
box-sizing: border-box;
margin: 26px 30px;
}
.list-box {
padding-bottom: 220px;
}
.lb-title {
font-size: 28px;
font-weight: 400;
line-height: 38px;
color: #707070;
border-top: 1px dashed #e4e4e4;
padding: 26px 46px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
}
.lb-t-serach {
@include flex-vertical-center;
height: 100px;
}
.lb-t-serach .icon-a-sousuo1 {
font-size: 38px;
color: #cccccc;
}
.lb-t-serach .lb-t-search-content {
display: flex;
justify-content: flex-end;
}
.lb-t-serach .lb-t-search-content > text {
padding: 10px 0;
color: #707070;
font-size: 24px;
}
.lb-t-search-content > view {
@include flex-vertical-center;
width: 280px;
height: 66px;
background-color: #e7e7e7;
border-radius: 30px;
margin-right: 10px;
font-size: 28px;
padding-left: 20px;
padding-right: 10px;
overflow: hidden;
}
.lb-title input {
width: 80%;
height: 66px;
background-color: #e7e7e7;
font-size: 26px;
}
.lb-t-search-content text {
color: #fff;
font-size: 30px;
}
.lb-t-sc-clear {
width: 66px;
height: 66px;
text-align: center;
line-height: 66px;
}
.lb-t-sc-clear .icon-a-cuowuwrong {
width: 43px;
height: 43px;
text-align: center;
line-height: 43px;
border-radius: 50%;
background: #c7c7c7;
display: inline-block;
}
.not-list {
font-size: 28px;
font-weight: 400;
line-height: 38px;
color: #707070;
margin-top: 180px;
text-align: center;
}
.lab-view {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 100;
background-color: rgba(0, 0, 0, 1);
}
.lab-view view {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 0;
padding-bottom: 100%;
}
.fixedBottom-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
width: 750px;
height: 182px;
background: #f3f3f3;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.16);
padding: 35px 68px;
box-sizing: border-box;
}
.fixedBottom-container view {
width: 264px;
height: 82px;
background: #ffffff;
opacity: 1;
border-radius: 50px;
display: flex;
justify-content: center;
align-items: center;
font-size: 32px;
font-weight: 400;
line-height: 42px;
color: #007aff;
}
.fixedBottom-container .fb-confirm {
background-color: #007aff;
color: white;
}
+136
View File
@@ -0,0 +1,136 @@
import { View, Input, Text } from '@tarojs/components'
import { FC, useMemo, useState } from 'react'
import LinkBlueTooth from '../components/bluetooth/LinkBlueTooth'
import SelectProduct from '@/components/selectProduct/index'
import styles from './index.module.scss'
import ColorCard from './components/ColorCard'
import IconFont from '@/components/iconfont'
import { ColorListApi, ColorDetailedApi, TextureSaveApi, ColorSamplingSaveApi } from '@/api/index'
import { formatHashTag } from '@/common/format'
// 颜色取样
const TakeColor: FC = () => {
const { state, fetchData } = ColorListApi()
const { state: detail, fetchData: detailFetchData } = ColorDetailedApi()
const { state: textureSaveData, fetchData: textureSaveFetchData } = TextureSaveApi()
const { state: saveData, fetchData: saveFetchData, success: saveSuccess } = ColorSamplingSaveApi()
const [searchValue, setSearchValue] = useState('')
const selectInput = async (event) => {
// if (event) {
// selectedProduct.value = event
// await fetchData({ id: event.id })
// data.value?.list.map((item, index) => {
// item.currnetRgb = item.rgb
// item.currentLab = item.lab
// item.sampling = !(item.currentLab?.l == 0 && item.currentLab?.a == 0 && item.currentLab?.b == 0)
// item.moveBorder = 0
// item.key = index
// })
// detailFetchData({ id: event.id })
// } else {
// data.value.list = []
// }
}
const clearSearchValue = () => {
setSearchValue('')
}
const handleTransfSearch = (bool: boolean) => {
setShowScreen(bool)
}
const handlePrViewRgb = (event) => {
setLabPreview(event)
setShowLabPreview(true)
}
const handleTakeColor = () => {}
const listData = useMemo(() => {
return state.data?.list?.filter((item) => {
if (searchValue) {
return formatHashTag(item.product_color_name, item.product_color_code)!.includes(searchValue)
}
return true
})
}, [state])
const [showScreen, setShowScreen] = useState(false)
const onSearchInput = (event) => {
const current = event.detail.value
setSearchValue(current)
}
// 重置
const handleReset = () => {}
// 提交
const handleSubmit = () => {}
const [labPreview, setLabPreview] = useState({
currnetRgb: {
r: 0,
g: 0,
b: 0,
},
})
const [showLabPreview, setShowLabPreview] = useState(false)
return (
<>
<View className={styles.card}>
<LinkBlueTooth />
<SelectProduct onSelect={selectInput} />
</View>
<View className={styles['list-box']}>
<View className={styles['lb-title']}>
<Text>颜色列表({listData?.length ?? 0})</Text>
<View className={styles['lb-t-serach']}>
{showScreen ? (
<View className={styles['lb-t-search-content']}>
<View>
<Input value={searchValue} type='text' onInput={onSearchInput} placeholder='筛选颜色或颜色编号' />
<View onClick={clearSearchValue} className={styles['lb-t-sc-clear']}>
{searchValue.length > 0 && <IconFont name='icon-guanbi' size={56}></IconFont>}
</View>
</View>
<Text onClick={() => handleTransfSearch(false)}>取消</Text>
</View>
) : (
<View onClick={() => handleTransfSearch(true)}>
<IconFont name='icon-sousuo' size={56}></IconFont>
</View>
)}
</View>
</View>
{listData ? (
listData.map((item, index) => {
return <ColorCard onPreviewRgb={handlePrViewRgb} onTakeColor={handleTakeColor} key={index} item={item} index={item.key} />
})
) : (
<View className={styles['not-list']}>-请取色-</View>
)}
</View>
<View className={styles['fixedBottom-container']}>
<View onClick={handleReset}>重置</View>
<View onClick={handleSubmit} className={styles['fb-confirm']}>
提交
</View>
</View>
{showLabPreview && (
<View catchMove onClick={() => setShowLabPreview(false)} className={styles['lab-view']}>
<View
style={{
backgroundColor: `rgb(
${labPreview?.currnetRgb?.r},
${labPreview?.currnetRgb?.g},
${labPreview?.currnetRgb?.b}
)`,
}}></View>
</View>
)}
</>
)
}
export default TakeColor
@@ -1,74 +1,71 @@
import { formatImgUrl } from "@/common/fotmat";
import { Image, Text, View } from "@tarojs/components";
import { memo, useEffect, useMemo, useRef, useState } from "react";
import classnames from "classnames";
import styles from './index.module.scss'
import dayjs from "dayjs";
import { useTimeCountDown } from "@/use/useCommon";
import { ORDER_STATUS, PAYMENT_METHOD } from "@/common/enum";
import { formatImgUrl } from '@/common/format'
import { Image, Text, View } from '@tarojs/components'
import { memo, useEffect, useMemo, useRef, useState } from 'react'
import classnames from 'classnames'
import styles from './index.module.scss'
import dayjs from 'dayjs'
import { useTimeCountDown } from '@/use/useCommon'
import { ORDER_STATUS, PAYMENT_METHOD } from '@/common/enum'
type List = {
status: string,
time: string,
tag: string,
desc: string,
expire_time: string
status: string
time: string
tag: string
desc: string
expire_time: string
}
type Param = {
onRefresh?: () => void,
orderInfo?: {
logistics_details:List[], //订单状态列表
payment_method: number, //支付方式
status: number, //订单状态
}
onRefresh?: () => void
orderInfo?: {
logistics_details: List[] //订单状态列表
payment_method: number //支付方式
status: number //订单状态
}
}
export default memo(({ orderInfo, onRefresh }: Param) => {
const { showTime, onStart, timeStatus } = useTimeCountDown()
export default memo(({orderInfo, onRefresh}:Param) => {
//订单状态枚举
const { SaleorderstatusWaitingPrePayment } = ORDER_STATUS
const {showTime, onStart, timeStatus} = useTimeCountDown()
//获取预付款最后时间
const endTime = useMemo(() => {
if (orderInfo?.status == SaleorderstatusWaitingPrePayment.value && orderInfo.logistics_details.length > 0) {
return orderInfo.logistics_details[0].expire_time
}
return ''
}, [orderInfo])
//订单状态枚举
const {SaleorderstatusWaitingPrePayment} = ORDER_STATUS
useEffect(() => {
if (endTime) onStart(endTime)
}, [endTime])
//获取预付款最后时间
const endTime = useMemo(() => {
if(orderInfo?.status == SaleorderstatusWaitingPrePayment.value && orderInfo.logistics_details.length > 0) {
return orderInfo.logistics_details[0].expire_time
}
return ''
}, [orderInfo])
useEffect(() => {
if (timeStatus == 2) onRefresh?.()
}, [timeStatus])
useEffect(() => {
if(endTime) onStart(endTime)
}, [endTime])
useEffect(() => {
if(timeStatus == 2) onRefresh?.()
}, [timeStatus])
return (
<View className={styles.advance_main}>
<View className={styles.time_con}>
<View className={styles.times}>
<Text className={styles.text}>剩</Text>
<Text className={styles.num}>{showTime.HH}</Text>
<Text className={styles.separate}>:</Text>
<Text className={styles.num}>{showTime.MM}</Text>
<Text className={styles.separate}>:</Text>
<Text className={styles.num}>{showTime.SS}</Text>
</View>
<Text>支付关闭,订单自动取消</Text>
</View>
<View className={styles.cardIcon}>
<Image className={styles.image} src={formatImgUrl("/mall/my_cart.png")}/>
</View>
<View className={styles.refresh} onClick={() => onRefresh?.()}>
<Text className={classnames(styles.mconfont, 'iconfont icon-shuaxin')}></Text>
<Text className={classnames(styles.refresh_text)}>刷新</Text>
</View>
return (
<View className={styles.advance_main}>
<View className={styles.time_con}>
<View className={styles.times}>
<Text className={styles.text}>剩</Text>
<Text className={styles.num}>{showTime.HH}</Text>
<Text className={styles.separate}>:</Text>
<Text className={styles.num}>{showTime.MM}</Text>
<Text className={styles.separate}>:</Text>
<Text className={styles.num}>{showTime.SS}</Text>
</View>
)
})
<Text>支付关闭,订单自动取消</Text>
</View>
<View className={styles.cardIcon}>
<Image className={styles.image} src={formatImgUrl('/mall/my_cart.png')} />
</View>
<View className={styles.refresh} onClick={() => onRefresh?.()}>
<Text className={classnames(styles.mconfont, 'iconfont icon-shuaxin')}></Text>
<Text className={classnames(styles.refresh_text)}>刷新</Text>
</View>
</View>
)
})
+3 -3
View File
@@ -3,9 +3,9 @@ import React, { useCallback, memo, useEffect, useMemo, useRef, useState } from '
import Search from '@/components/search'
import styles from "./index.module.scss"
import classnames from "classnames";
import Empty from './compoents/empty'
import Empty from './components/empty'
import Taro from '@tarojs/taro';
import Goods from './compoents/goods'
import Goods from './components/goods'
import { mpproductlist } from "@/api/search"
export default memo(() => {
@@ -95,4 +95,4 @@ export default memo(() => {
</View>
)
})
})
+3 -3
View File
@@ -65,17 +65,17 @@ const fabric: IconCardType[] = [
{
iconName: 'icon-yansequyang',
name: '颜色取样',
path: '',
path: '/pages/colorRelated/takeColor/index',
},
{
iconName: 'icon-qusechazhao',
name: '取色查找',
path: '',
path: '/pages/colorRelated/findColor/index',
},
{
iconName: 'icon-yangpinduibi',
name: '样品对比',
path: '/pages/sampleComparison/index',
path: '/pages/colorRelated/sampleComparison/index',
},
]