🦄 refactor(ID1000779): 八、收藏功能;
【八、收藏功能;】 https://www.tapd.cn/53459131/prong/stories/view/1153459131001000779
This commit is contained in:
parent
debbbfa3ce
commit
7344025716
@ -5,3 +5,4 @@
|
||||
project.*.json
|
||||
*.lock
|
||||
*.log
|
||||
iconfont/
|
||||
|
||||
@ -78,7 +78,7 @@
|
||||
"prettier": "^2.8.0",
|
||||
"react-refresh": "0.14.0",
|
||||
"stylelint": "14.16.0",
|
||||
"taro-iconfont-cli": "^3.3.0",
|
||||
"taro-iconfont-svg": "^1.0.19",
|
||||
"typescript": "^4.9.3",
|
||||
"webpack": "^5.75.0"
|
||||
}
|
||||
|
||||
@ -1,12 +1,21 @@
|
||||
{
|
||||
"projectname": "EShop",
|
||||
"setting": {
|
||||
"compileHotReLoad": true
|
||||
"compileHotReLoad": true,
|
||||
"bigPackageSizeSupport": true,
|
||||
"urlCheck": false
|
||||
},
|
||||
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
|
||||
"condition": {
|
||||
"miniprogram": {
|
||||
"list": [
|
||||
{
|
||||
"name": "收藏夹",
|
||||
"pathName": "pages/collection/collectionDetail/index",
|
||||
"query": "",
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"pathName": "pages/sampleComparison/index",
|
||||
@ -14,7 +23,8 @@
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,6 +171,7 @@ export default {
|
||||
pages: [
|
||||
'index',
|
||||
'collectionClass/index',
|
||||
'collectionDetail/index',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@ -2,7 +2,8 @@ import Taro from '@tarojs/taro'
|
||||
import Qs from 'qs'
|
||||
|
||||
const setUrlQuery = (options: { url: string; query: object | null }) => {
|
||||
let { url, query } = options
|
||||
let { url } = options
|
||||
const { query } = options
|
||||
if (!url) { return '' }
|
||||
if (query) {
|
||||
const queryArr: any[] = []
|
||||
|
||||
@ -12,7 +12,7 @@ export const BASE_URL = CURRENT_BASE_URL
|
||||
// export const BASE_URL = `https://dev.zzfzyc.com/lymarket` // 开发环境
|
||||
// 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.7:50002/lymarket' // 添
|
||||
// export const BASE_URL = 'http://192.168.1.28:50002/lymarket' // 婷
|
||||
// export const BASE_URL = `http://192.168.1.42:50002/lymarket` // 杰
|
||||
|
||||
|
||||
24
src/components/InputX/index.tsx
Normal file
24
src/components/InputX/index.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { CustomWrapper, Input, View } from '@tarojs/components'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
// 解决 input 组件输入过快会出现闪烁的问题
|
||||
// https://github.com/NervJS/taro/issues/9664
|
||||
interface PropsType {
|
||||
customClassName?: string
|
||||
customStyle?: React.CSSProperties
|
||||
customInputStyle?: React.CSSProperties
|
||||
customInputClassName?: string
|
||||
[Property: string]: any
|
||||
}
|
||||
const InputX: FC<PropsType> = (props) => {
|
||||
const { customClassName, customStyle, customInputStyle, customInputClassName, ...inputProps } = props
|
||||
return (
|
||||
<View className={customClassName} style={customStyle}>
|
||||
<CustomWrapper>
|
||||
<Input className={customInputClassName} style={customInputStyle} {...inputProps} ></Input>
|
||||
</CustomWrapper>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default InputX
|
||||
@ -1,47 +1,32 @@
|
||||
|
||||
.collection_con{
|
||||
padding: 20px ;
|
||||
.header{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
.title{
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.miconfont_con{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 0;
|
||||
font-size: 26px;
|
||||
color: #007AFF;
|
||||
.miconfont{
|
||||
font-size: 30px;
|
||||
color: #007AFF;
|
||||
border: 1px solid #007AFF;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.collection_con {
|
||||
.collection_item {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
font-size: 26px;
|
||||
padding: 0px 32px;
|
||||
align-items: center;
|
||||
.collectionImage {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
background-color: #f6f6f6;
|
||||
border: 1px solid #dedede;
|
||||
border-radius: 5px;
|
||||
margin-right: 32px;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.scrollView{
|
||||
height: 60vh;
|
||||
.miconfont {
|
||||
font-size: 36px;
|
||||
color: #007aff;
|
||||
}
|
||||
.collection_item{
|
||||
padding: 30px 0 15px 0;
|
||||
border-bottom: 1px solid #F3F3F3;
|
||||
.name{
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
text{
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
.desc{
|
||||
font-size: 22px;
|
||||
color: #707070;
|
||||
padding-left: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.text {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.scrollStyle {
|
||||
max-height: 60vh;
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { Input, ScrollView, Text, View } from '@tarojs/components'
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import IconFont from '../iconfont/iconfont'
|
||||
import Divider from '../divider'
|
||||
import styles from './index.module.scss'
|
||||
import Popup from '@/components/popup'
|
||||
import TextareaEnhance from '@/components/textareaEnhance'
|
||||
@ -9,14 +11,17 @@ import { alert, goLink } from '@/common/common'
|
||||
import { getFilterData } from '@/common/util'
|
||||
|
||||
// 原因选择
|
||||
interface ReasonInfoParam {
|
||||
interface AddCollectionParam {
|
||||
show?: boolean // 显示
|
||||
onClose?: () => void // 关闭
|
||||
onAdd?: (val: any) => void
|
||||
}
|
||||
const AddCollection = ({ show = false, onClose, onAdd }: ReasonInfoParam) => {
|
||||
const AddCollection = (props: AddCollectionParam) => {
|
||||
const {
|
||||
show = false, onClose, onAdd,
|
||||
} = props
|
||||
// 获取列表
|
||||
const [list, setList] = useState([])
|
||||
const [list, setList] = useState<any[]>([])
|
||||
const { fetchData: fetchDataList } = FavoriteListApi()
|
||||
const getFavoriteList = async() => {
|
||||
const res = await fetchDataList(getFilterData())
|
||||
@ -25,35 +30,38 @@ const AddCollection = ({ show = false, onClose, onAdd }: ReasonInfoParam) => {
|
||||
useEffect(() => {
|
||||
if (show) { getFavoriteList() }
|
||||
}, [show])
|
||||
|
||||
const onCreate = () => {
|
||||
onClose?.()
|
||||
goLink('/pages/collection/index')
|
||||
const handleNewCollection = () => {
|
||||
// 新建收藏夹
|
||||
goLink('/pages/collection/collectionDetail/index', { title: '新建收藏夹', isEdit: false, editData: null })
|
||||
}
|
||||
|
||||
return (
|
||||
<Popup show={show} onClose={onClose} showTitle={false}>
|
||||
<View className={styles.collection_con}>
|
||||
<View className={styles.header}>
|
||||
<Text className={styles.title}>选择收藏夹</Text>
|
||||
<View className={styles.miconfont_con}>
|
||||
<Text className={classnames(styles.miconfont, 'iconfont icon-jia')}></Text>
|
||||
<Text onClick={onCreate}>新建</Text>
|
||||
</View>
|
||||
</View>
|
||||
<ScrollView scrollY className={styles.scrollView}>
|
||||
{list?.map((item: any, index) => (
|
||||
<View key={index} onClick={() => onAdd?.(item)} className={styles.collection_item}>
|
||||
<View className={styles.name}>
|
||||
{item.name}
|
||||
<Text>({item.product_color_list?.length || 0})</Text>
|
||||
</View>
|
||||
<View className={styles.desc}>{item.remark}</View>
|
||||
<Popup show={show} onClose={onClose} showTitle title="加入收藏夹" >
|
||||
<Divider direction="horizontal" customStyles={{ marginTop: '0px', marginBottom: '12px' }}></Divider>
|
||||
<ScrollView className={styles.scrollStyle} scrollY>
|
||||
<View className={styles.collection_con}>
|
||||
{
|
||||
list.map((item, key) => (
|
||||
<>
|
||||
<View key={key} className={styles.collection_item} onClick={() => onAdd?.(item)}>
|
||||
<View className={styles.collectionImage}></View>
|
||||
<Text className={styles.text}>{item.name}</Text>
|
||||
</View>
|
||||
<Divider direction="horizontal" customStyles={{ margin: '12px 0' }}></Divider>
|
||||
</>
|
||||
))
|
||||
}
|
||||
<View className={styles.collection_item} onClick={handleNewCollection}>
|
||||
<View className={styles.collectionImage}>
|
||||
<IconFont name="icon-xinzengshoucangjia" size={40}></IconFont>
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
</View>
|
||||
<Text className={styles.text}>新建收藏夹</Text>
|
||||
</View>
|
||||
<Divider direction="horizontal" customStyles={{ margin: '12px 0' }}></Divider>
|
||||
|
||||
</View>
|
||||
</ScrollView>
|
||||
</Popup>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(AddCollection)
|
||||
|
||||
@ -1,32 +1,56 @@
|
||||
.checkbox_main{
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&--text {
|
||||
color: currentColor;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.checkbox_item{
|
||||
.checkbox_main {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
border: 1px solid #c2c2c2;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
line-height: 40px;
|
||||
&--normal {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 1px solid #707070;
|
||||
}
|
||||
&--small {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
&--round {
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
background-color: #fff;
|
||||
}
|
||||
&--circle {
|
||||
border-radius: 10px;
|
||||
}
|
||||
// 选中
|
||||
&--selected {
|
||||
border-color: $color_main;
|
||||
}
|
||||
}
|
||||
.no_checkbox_item{
|
||||
border:0;
|
||||
background-color: #DDDDDD;
|
||||
.checkbox_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.no_checkbox_item {
|
||||
border: 0;
|
||||
background-color: #dddddd;
|
||||
}
|
||||
.checkbox_item_select {
|
||||
background-color: $color_main;
|
||||
border: 0;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
}
|
||||
.checkbox_item_select{
|
||||
background-color: $color_main;
|
||||
border: 0;
|
||||
color: #fff;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
line-height: 40px;
|
||||
.miconfont{
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
@ -1,16 +1,61 @@
|
||||
import { View } from '@tarojs/components'
|
||||
import classnames from 'classnames'
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
|
||||
import React, { SetStateAction, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'
|
||||
import IconFont from '../iconfont/iconfont'
|
||||
import styles from './index.module.scss'
|
||||
import { usePropsValue } from '@/use/useCommon'
|
||||
|
||||
type CheckboxSize = 'normal' | 'small'
|
||||
|
||||
interface params {
|
||||
onSelect?: () => void // 选择触发
|
||||
onClose?: () => void // 取消触发
|
||||
status?: false | true // 是否选中
|
||||
disabled?: false | true // 是否禁用
|
||||
status?: boolean // 是否选中
|
||||
hiddenCheckboxIcon?: boolean // 隐藏多选框
|
||||
disabled?: boolean // 是否禁用
|
||||
triggerLabel?: boolean // 点击label是否触发选中
|
||||
circle?: boolean
|
||||
round?: boolean
|
||||
size?: CheckboxSize
|
||||
children?: React.ReactNode
|
||||
customStyles?: React.CSSProperties
|
||||
customClassName?: string
|
||||
customTextClass?: string
|
||||
}
|
||||
const Checkbox = ({ onSelect, onClose, status = false, disabled = false }: params, ref) => {
|
||||
const [selected, SetSelected] = useState(false)
|
||||
const Checkbox = (props: params, ref) => {
|
||||
const {
|
||||
onSelect,
|
||||
onClose,
|
||||
status = false,
|
||||
disabled = false,
|
||||
circle = false,
|
||||
round = true,
|
||||
triggerLabel = true,
|
||||
size = 'normal',
|
||||
children,
|
||||
customStyles = {},
|
||||
customClassName = '',
|
||||
customTextClass = '',
|
||||
hiddenCheckboxIcon = false,
|
||||
} = props
|
||||
const [selected, setSelected] = usePropsValue({
|
||||
value: status,
|
||||
defaultValue: false,
|
||||
})
|
||||
// const selectedRef = useRef(status)
|
||||
// if (status !== undefined){
|
||||
// selectedRef.current = status
|
||||
// }
|
||||
// const [, setForceUpdate] = useState({})
|
||||
// const setSelected = useCallback((v: SetStateAction<boolean>) => {
|
||||
// const nextValue = typeof v === 'function' ? (v as (prevValue: boolean) => boolean)(selectedRef.current) : v
|
||||
// console.log('对比',nextValue, selectedRef.current)
|
||||
// if (nextValue === selectedRef.current) return
|
||||
// selectedRef.current = nextValue
|
||||
// console.log('强制刷新', nextValue, selectedRef.current)
|
||||
// setForceUpdate({})
|
||||
// }, [])
|
||||
|
||||
const onSelectEven = () => {
|
||||
if (disabled) { return false }
|
||||
const res = !selected
|
||||
@ -20,22 +65,56 @@ const Checkbox = ({ onSelect, onClose, status = false, disabled = false }: param
|
||||
else {
|
||||
onClose?.()
|
||||
}
|
||||
SetSelected(res)
|
||||
console.log('res', res)
|
||||
setSelected(res)
|
||||
}
|
||||
|
||||
const handleClickChildren = (event) => {
|
||||
if (!triggerLabel) {
|
||||
return event.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
const getMainClassName = () => {
|
||||
const classObject = {
|
||||
[styles['checkbox_main--selected']]: selected,
|
||||
[styles[`checkbox_main--${size}`]]: size,
|
||||
[styles['checkbox_main--round']]: round,
|
||||
[styles['checkbox_main--circle']]: circle,
|
||||
}
|
||||
return classObject
|
||||
}
|
||||
|
||||
const getClassName = () => {
|
||||
const classObject = {
|
||||
[styles.no_checkbox_item]: disabled,
|
||||
[styles.checkbox_item_select]: selected,
|
||||
}
|
||||
return classObject
|
||||
}
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
onSelectEven,
|
||||
}))
|
||||
useEffect(() => {
|
||||
SetSelected(status)
|
||||
}, [status])
|
||||
// useEffect(() => {
|
||||
// setSelected(status)
|
||||
// }, [status])
|
||||
return (
|
||||
<>
|
||||
<View className={styles.checkbox_main} onClick={() => onSelectEven()}>
|
||||
<View className={classnames(styles.checkbox_item, disabled && styles.no_checkbox_item, selected && styles.checkbox_item_select)}>
|
||||
{selected && <View className={classnames('iconfont', 'icon-tick', styles.miconfont)}></View>}
|
||||
<View className={classnames(customClassName, styles.checkbox)} style={customStyles} onClick={onSelectEven}>
|
||||
{!hiddenCheckboxIcon && (
|
||||
<View className={classnames(styles.checkbox_main, getMainClassName())}>
|
||||
<View className={classnames(styles.checkbox_item, getClassName())}>
|
||||
{selected && <IconFont name="icon-xuanzechenggong" size={22} color="#fff"></IconFont>}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
|
||||
{children && (
|
||||
<View className={classnames(styles['checkbox--text'], customTextClass)} onClick={handleClickChildren}>
|
||||
{children}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
export default forwardRef(Checkbox)
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
.icon_a_cuowuwrong_self {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
font-size: 27px;
|
||||
padding: 10px;
|
||||
border-radius: 50%;
|
||||
border: #ccc 1px solid;
|
||||
color: #ccc;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.icon_a_btn{
|
||||
font-size: 30px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
font-size: 27px;
|
||||
padding: 10px;
|
||||
border-radius: 50%;
|
||||
color: #ccc;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.icon_a_btn {
|
||||
font-size: 30px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Text, View } from '@tarojs/components'
|
||||
import { memo } from 'react'
|
||||
import IconFont from '../iconfont/iconfont'
|
||||
import style from './index.module.scss'
|
||||
|
||||
interface Params {
|
||||
@ -13,7 +14,9 @@ const CloseBtn = ({ onClose, styleObj = {} }: Params) => {
|
||||
className={style.icon_a_cuowuwrong_self}
|
||||
onClick={onClose}
|
||||
>
|
||||
<Text className={`iconfont icon-qingkong ${style.icon_a_btn}`}></Text>
|
||||
<View className={style.icon_a_btn}>
|
||||
<IconFont name="icon-qingchuxinxi" size={40} color="#acacac"></IconFont>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
47
src/components/divider/index.module.scss
Normal file
47
src/components/divider/index.module.scss
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
.divider {
|
||||
position: relative;
|
||||
font-size: 28px;
|
||||
color: $color_font_one;
|
||||
// 垂直
|
||||
&-vertical {
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 1em;
|
||||
margin: 0 8px;
|
||||
border-left: 1px $borderStyle $borderColor;
|
||||
vertical-align: middle;
|
||||
}
|
||||
// 水平
|
||||
&-horizontal {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
margin: 48px 0;
|
||||
border-top: 1px $borderStyle $borderColor;
|
||||
}
|
||||
&-text{
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
padding: 0 40px;
|
||||
font-size: inherit;
|
||||
font-weight: 500;
|
||||
color: currentColor;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
.is{
|
||||
&-center{
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
}
|
||||
&-left{
|
||||
left: 20px;
|
||||
transform:translateY(-50%);
|
||||
}
|
||||
&-right{
|
||||
right: 20px;
|
||||
transform:translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
47
src/components/divider/index.tsx
Normal file
47
src/components/divider/index.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* <View>巴拉巴拉小魔仙</View>
|
||||
* <Divider direction="vertical" borderStyle="solid"></Divider
|
||||
* <View>全身变</View>
|
||||
*
|
||||
*/
|
||||
|
||||
import { View } from '@tarojs/components'
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
type BorderStype = 'solid' | 'dashed' | 'dotted' | 'double'
|
||||
|
||||
interface DividerProps {
|
||||
direction?: 'horizontal' | 'vertical'
|
||||
borderStyle?: BorderStype
|
||||
contentPosition?: 'left' | 'center' | 'right'
|
||||
children?: ReactNode
|
||||
customClassName?: string
|
||||
customStyles?: React.CSSProperties
|
||||
}
|
||||
const Divider: FC<DividerProps> = (props) => {
|
||||
const { direction = 'horizontal', borderStyle = 'solid', contentPosition = 'center', customClassName = '', customStyles = {} } = props
|
||||
|
||||
const classname = classnames(styles.divider, styles[`divider-${direction}`], customClassName)
|
||||
const contentClassname = classnames(styles['divider-text'], styles[`is-${contentPosition}`])
|
||||
|
||||
const borderTopStyle: { borderTopStyle: BorderStype } = {
|
||||
borderTopStyle: borderStyle,
|
||||
}
|
||||
const borderLeftStyle: { borderLeftStyle: BorderStype } = {
|
||||
borderLeftStyle: borderStyle,
|
||||
}
|
||||
|
||||
const dividerStyle = direction === 'horizontal' ? borderTopStyle : borderLeftStyle
|
||||
|
||||
return (
|
||||
<View className={classname} style={{ ...dividerStyle, ...customStyles }}>
|
||||
{props.children && direction !== 'vertical' && <View className={contentClassname}>{props.children}</View>}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
export default Divider
|
||||
20
src/components/iconText/index.module.scss
Normal file
20
src/components/iconText/index.module.scss
Normal file
@ -0,0 +1,20 @@
|
||||
.iconText{
|
||||
display: flex;
|
||||
font-size: 28px;
|
||||
.iconfont{
|
||||
font-size: 40px;
|
||||
}
|
||||
.text{
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
// 水平方向
|
||||
.iconText--horizontal{
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
// 垂直方向
|
||||
.iconText--vertical{
|
||||
flex-flow: column nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
56
src/components/iconText/index.tsx
Normal file
56
src/components/iconText/index.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import { Text, View } from '@tarojs/components'
|
||||
import type { FC } from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import type { IconNames } from '../iconfont/iconfont'
|
||||
import IconFont from '../iconfont/iconfont'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
type Direaction = 'left' | 'right' | 'bottom' | 'top'
|
||||
|
||||
interface PropsType {
|
||||
iconName: IconNames
|
||||
iconSize?: number
|
||||
svg?: boolean
|
||||
color?: string
|
||||
text?: string
|
||||
direction?: Direaction
|
||||
children?: React.ReactNode
|
||||
customClass?: string
|
||||
customStyle?: React.CSSProperties
|
||||
textClassName?: string
|
||||
textCustomStyle?: React.CSSProperties
|
||||
}
|
||||
|
||||
const IconText: FC<PropsType> = (props) => {
|
||||
const { children, svg = false, iconName, iconSize = 40, text = '', color, textCustomStyle, direction = 'left' } = props
|
||||
const classNameObject = {
|
||||
[styles['iconText--horizontal']]: ['left', 'right'].includes(direction),
|
||||
[styles['iconText--vertical']]: ['bottom', 'top'].includes(direction),
|
||||
}
|
||||
const iconComponent = svg ? <IconFont name={iconName} size={iconSize} color={color}></IconFont> : <Text className={classnames('iconfont', iconName, styles.iconfont)}></Text>
|
||||
|
||||
const textComponent = children || <Text className={classnames(props.textClassName, styles.text)} style={textCustomStyle}>{text}</Text>
|
||||
|
||||
const component = () => {
|
||||
if (direction === 'left' || direction === 'top') {
|
||||
return <>
|
||||
{iconComponent}
|
||||
{textComponent}
|
||||
</>
|
||||
}
|
||||
else if (direction === 'right' || direction === 'bottom') {
|
||||
return <>
|
||||
{textComponent}
|
||||
{iconComponent}
|
||||
</>
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={classnames(styles.iconText, classNameObject, props.customStyle, props.customClass)}>
|
||||
{component()}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
export default IconText
|
||||
3
src/components/iconfont/iconfont.scss
Normal file
3
src/components/iconfont/iconfont.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.icon {
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
177
src/components/iconfont/iconfont.tsx
Normal file
177
src/components/iconfont/iconfont.tsx
Normal file
@ -0,0 +1,177 @@
|
||||
import React, { useState, useEffect, FC } from "react";
|
||||
import { Block, View } from "@tarojs/components";
|
||||
import "./iconfont.scss";
|
||||
import Taro from "@tarojs/taro";
|
||||
import classnames from "classnames";
|
||||
|
||||
const SystemWidth = Taro.getSystemInfoSync().windowWidth
|
||||
const quot = '"'
|
||||
|
||||
function hex2rgb(hex) {
|
||||
const rgb: number[] = [];
|
||||
|
||||
hex = hex.substr(1);
|
||||
|
||||
if (hex.length === 3) {
|
||||
hex = hex.replace(/(.)/g, "$1$1");
|
||||
}
|
||||
|
||||
hex.replace(/../g, function(color: string) {
|
||||
rgb.push(parseInt(color, 0x10));
|
||||
return color;
|
||||
});
|
||||
|
||||
return "rgb(" + rgb.join(",") + ")";
|
||||
}
|
||||
|
||||
export type IconNames = 'icon-xinzengshoucangjia' | 'icon-qingchusousuo' | 'icon-xuanzechenggong' | 'icon-gongnengtubiao-saomiao' | 'icon-bianjizidingyimadan' | 'icon-zidingyimadanyulan' | 'icon-yuanshimadanyulan' | 'icon-xiala' | 'icon-shangla' | 'icon-qingchuxinxi' | 'icon-sousuo' | 'icon-guanli' | 'icon-bianji' | 'icon-shoucangjia' | 'icon-shezhi' | 'icon-tishi' | 'icon-erweima' | 'icon-dianjishoucang' | 'icon-gouwuche' | 'icon-shoucangchenggong' | 'icon-fenxiangshangpin' | 'icon-kefu' | 'icon-xinzenganniu' | 'icon-jianshaoanniu' | 'icon-daifahuo2' | 'icon-daishouhuo2' | 'icon-tuikuan-shouhou' | 'icon-daipeibu2' | 'icon-daifukuan2';
|
||||
|
||||
type PropsType = {
|
||||
name: IconNames;
|
||||
size?: number;
|
||||
color?: string | string[];
|
||||
customStyle?: React.CSSProperties;
|
||||
customClassName?: string;
|
||||
};
|
||||
|
||||
const IconFont:FC<PropsType> = ({
|
||||
name,
|
||||
size = 36,
|
||||
color,
|
||||
customStyle = {},
|
||||
customClassName = ""
|
||||
}) => {
|
||||
const [colors, setColors] = useState<PropsType['color']>()
|
||||
const [isStr, setIsStr] = useState(true)
|
||||
const [svgSize, setSvgSize] = useState(() => (size / 750) * SystemWidth)
|
||||
|
||||
useEffect(() => {
|
||||
setIsStr(typeof color === 'string')
|
||||
if (typeof color === 'string') {
|
||||
setColors(color.indexOf('#') === 0 ? hex2rgb(color) : color)
|
||||
} else {
|
||||
setColors(
|
||||
color?.map(function (item) {
|
||||
return item.indexOf('#') === 0 ? hex2rgb(item) : item
|
||||
})
|
||||
)
|
||||
}
|
||||
return () => {}
|
||||
}, [color])
|
||||
|
||||
useEffect(() => {
|
||||
setSvgSize((size / 750) * SystemWidth)
|
||||
}, [size])
|
||||
|
||||
// 也可以使用 if (name === 'xxx') { return <view> } 来渲染,但是测试发现在ios下会有问题,报错 Maximum call stack啥的。下面这个写法没问题
|
||||
return (
|
||||
<Block>
|
||||
{/* icon-alipay */}
|
||||
{/* {name === "icon-alipay" && (
|
||||
<View
|
||||
style={{
|
||||
backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M192 692.736c0-69.632 51.2-106.496 88.064-111.104 111.104-18.432 264.192 74.24 264.192 74.24-69.632 88.064-166.912 134.144-241.152 134.144-65.024-4.608-111.104-41.472-111.104-97.28z' fill='${(isStr
|
||||
? colors
|
||||
: colors[0]) ||
|
||||
"rgb(91,139,212)"}' /%3E%3Cpath d='M979.456 729.6c-13.824-4.608-329.216-101.888-319.488-111.104 46.592-55.808 78.848-185.344 78.848-185.344v-27.648h-185.344V335.872h226.816v-41.472h-226.816V192.512H460.8v97.28H257.024v41.472H460.8v69.632H298.496v27.648h333.824c0 13.824-23.04 106.496-46.08 148.48-4.608-9.216-153.088-60.416-236.544-65.024-88.064 4.608-157.696 32.256-189.952 97.28-46.592 120.32 27.648 241.152 194.56 241.152 27.648 0 162.304-13.824 264.192-153.088 27.648 13.824 185.344 92.672 282.624 143.872-92.672 111.104-231.936 180.736-389.12 180.736-280.576 1.024-508.928-226.304-509.44-506.88v-3.072C1.024 231.424 227.84 3.072 508.928 2.56h3.072c280.576-1.024 508.928 226.304 509.44 506.88v3.072c4.608 82.944-13.824 152.576-41.984 217.088z' fill='${(isStr
|
||||
? colors
|
||||
: colors[1]) ||
|
||||
"rgb(91,139,212)"}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`,
|
||||
...customStyle
|
||||
}}
|
||||
className={classnames(icon, customClassName)}
|
||||
/>
|
||||
)} */}
|
||||
{/* icon-xinzengshoucangjia */}
|
||||
|
||||
{ name === 'icon-xinzengshoucangjia' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M0 458.105263h1024v107.789474H0z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(213,213,213)'}' /%3E%3Cpath d='M458.105263 1024V0h107.789474v1024z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(213,213,213)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-qingchusousuo */}
|
||||
|
||||
{ name === 'icon-qingchusousuo' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M512 96A176.0256 176.0256 0 0 1 687.2832 256h160.7168a32 32 0 0 1 0 64h-32v544a64 64 0 0 1-64 64h-480a64 64 0 0 1-64-64V320h-32a32 32 0 0 1 0-64h160.7168A176.0256 176.0256 0 0 1 512 96z m240 224h-480v544h480V320z m-336 128c17.664 0 32 14.336 32 32v224a32 32 0 0 1-64 0v-224c0-17.664 14.336-32 32-32z m192 0c17.664 0 32 14.336 32 32v224a32 32 0 0 1-64 0v-224c0-17.664 14.336-32 32-32zM512 160A112.0256 112.0256 0 0 0 401.152 256h221.696A112.0256 112.0256 0 0 0 512 160z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.5' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-xuanzechenggong */}
|
||||
|
||||
{ name === 'icon-xuanzechenggong' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1422 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M1337.193078 33.364407a113.774617 113.774617 0 0 1 0 160.877309L572.912086 958.579595a113.774617 113.774617 0 0 1-160.877309 0L33.335963 579.823894a113.774617 113.774617 0 0 1 160.877309-160.877309l298.260159 298.203272L1176.258882 33.364407a113.774617 113.774617 0 0 1 154.733479-5.802506l6.257604 5.802506z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(255,255,255)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-gongnengtubiao-saomiao */}
|
||||
|
||||
{ name === 'icon-gongnengtubiao-saomiao' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M176 640v208h208v64H144a32 32 0 0 1-32-32V640h64z m736 0v240a32 32 0 0 1-32 32H640v-64h208V640h64z m0-160v64H112v-64h800z m-32-368a32 32 0 0 1 32 32v240h-64V176H640v-64h240z m-496 0v64H176v208h-64V144a32 32 0 0 1 32-32h240z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(51,51,51)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-bianjizidingyimadan */}
|
||||
|
||||
{ name === 'icon-bianjizidingyimadan' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M0 0m89.043478 0l845.913044 0q89.043478 0 89.043478 89.043478l0 845.913044q0 89.043478-89.043478 89.043478l-845.913044 0q-89.043478 0-89.043478-89.043478l0-845.913044q0-89.043478 89.043478-89.043478Z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(231,240,255)'}' /%3E%3Cpath d='M545.391304 244.869565v233.739131H779.130435v66.782608H545.391304V779.130435h-66.782608V545.391304H244.869565v-66.782608h233.739131V244.869565h66.782608z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(51,127,255)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-zidingyimadanyulan */}
|
||||
|
||||
{ name === 'icon-zidingyimadanyulan' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M0 0m89.043478 0l845.913044 0q89.043478 0 89.043478 89.043478l0 845.913044q0 89.043478-89.043478 89.043478l-845.913044 0q-89.043478 0-89.043478-89.043478l0-845.913044q0-89.043478 89.043478-89.043478Z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(231,240,255)'}' /%3E%3Cpath d='M823.652174 222.608696v267.130434H200.347826V222.608696h623.304348z m-556.521739 66.782608v133.565218h133.565217v-133.565218h-133.565217z m200.347826 133.565218h289.391304v-133.565218H467.478261v133.565218z m356.173913 111.304348v267.130434H200.347826V534.26087h623.304348z m-422.956522 66.782608h-133.565217v133.565218h133.565217v-133.565218z m356.173913 0H467.478261v133.565218h289.391304v-133.565218z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(51,127,255)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-yuanshimadanyulan */}
|
||||
|
||||
{ name === 'icon-yuanshimadanyulan' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M0 0m89.043478 0l845.913044 0q89.043478 0 89.043478 89.043478l0 845.913044q0 89.043478-89.043478 89.043478l-845.913044 0q-89.043478 0-89.043478-89.043478l0-845.913044q0-89.043478 89.043478-89.043478Z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(231,240,255)'}' /%3E%3Cpath d='M756.869565 200.347826a22.26087 22.26087 0 0 1 22.26087 22.26087v578.782608a22.26087 22.26087 0 0 1-22.26087 22.26087H267.130435a22.26087 22.26087 0 0 1-22.26087-22.26087V222.608696a22.26087 22.26087 0 0 1 22.26087-22.26087h489.73913z m-44.521739 66.782609H311.652174v489.73913h400.695652V267.130435z m-66.782609 244.869565v66.782609H378.434783v-66.782609h267.130434z m0-133.565217v66.782608H378.434783v-66.782608h267.130434z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(51,127,255)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-xiala */}
|
||||
|
||||
{ name === 'icon-xiala' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M828.7744 397.7216a32 32 0 0 0-43.4944-1.6128l-1.7408 1.6128L512 669.2608 240.4608 397.7216a32 32 0 0 0-43.4944-1.6128l-1.7408 1.6128a32 32 0 0 0-1.6384 43.52l1.6384 1.7408 294.144 294.144a32 32 0 0 0 43.52 1.6384l1.7408-1.6384 294.144-294.144a32 32 0 0 0 0-45.2608z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.4' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-shangla */}
|
||||
|
||||
{ name === 'icon-shangla' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M828.7744 626.2784a32 32 0 0 1-43.4944 1.6128l-1.7408-1.6128L512 354.7392 240.4608 626.2784a32 32 0 0 1-43.4944 1.6128l-1.7408-1.6128a32 32 0 0 1-1.6384-43.52l1.6384-1.7408 294.144-294.144a32 32 0 0 1 43.52-1.6384l1.7408 1.6384 294.144 294.144a32 32 0 0 1 0 45.2608z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.4' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-qingchuxinxi */}
|
||||
|
||||
{ name === 'icon-qingchuxinxi' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M512 96c229.76 0 416 186.24 416 416S741.76 928 512 928 96 741.76 96 512 282.24 96 512 96z m-113.152 257.6128a32 32 0 1 0-45.2352 45.2608L466.7392 512l-113.152 113.152a32 32 0 0 0-2.304 42.6496l2.304 2.5856a32 32 0 0 0 45.2864 0L512 557.2608l113.152 113.152a32 32 0 0 0 42.6496 2.304l2.5856-2.304a32 32 0 0 0 0-45.2864L557.2608 512l113.152-113.152a32 32 0 0 0 2.304-42.6496l-2.304-2.5856a32 32 0 0 0-45.2864 0L512 466.7392z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.3' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-sousuo */}
|
||||
|
||||
{ name === 'icon-sousuo' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M718.3872 243.2c123.5968 123.6224 130.7904 319.5392 21.5296 451.5328l1.1008 1.024 135.7568 135.7824a32 32 0 0 1-45.2352 45.2352l-135.7824-135.7568-1.024-1.1008c-131.9936 109.2608-327.936 102.0672-451.5072-21.504-131.2256-131.2256-131.2256-343.9872 0-475.1872 131.2-131.2256 343.9616-131.2256 475.1616 0z m-45.2608 45.2608c-106.2144-106.2144-278.4256-106.2144-384.6656 0-106.2144 106.24-106.2144 278.4512 0 384.6656 97.9712 97.9712 253.4144 106.24 360.7552 21.2992l4.7104-3.8144 20.0704-16.6144 16.64-20.0704c87.6544-105.9072 82.0992-261.4528-13.2352-361.088l-4.2752-4.352z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.3' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-guanli */}
|
||||
|
||||
{ name === 'icon-guanli' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M800 96c44.1856 0 80 35.84 80 80v672c0 44.1856-35.84 80-80 80H224a80 80 0 0 1-80-80V176c0-44.1856 35.84-80 80-80z m0 64H224a16 16 0 0 0-16 16v672c0 8.832 7.168 16 16 16h576c8.832 0 16-7.168 16-16V176a16 16 0 0 0-16-16zM688 640a32 32 0 0 1 0 64h-352a32 32 0 0 1 0-64h352z m0-160a32 32 0 0 1 0 64h-352a32 32 0 0 1 0-64h352z m0-160a32 32 0 0 1 0 64h-352a32 32 0 0 1 0-64h352z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.8' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-bianji */}
|
||||
|
||||
{ name === 'icon-bianji' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M480 112a32 32 0 0 1 0 64H176v672h672V576a32 32 0 0 1 64 0v304a32 32 0 0 1-32 32h-736a32 32 0 0 1-32-32v-736a32 32 0 0 1 32-32H480z m454.624-22.624a32 32 0 0 1 1.888 43.2l-1.888 2.048-400 400a32 32 0 0 1-47.136-43.2l1.888-2.048 400-400a32 32 0 0 1 45.248 0z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(69,129,255)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-shoucangjia */}
|
||||
|
||||
{ name === 'icon-shoucangjia' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(222,243,253)'}' /%3E%3Cpath d='M768.256 402.6368c8.977067 0.9216 17.92 3.242667 26.897067 6.9632 8.977067 3.720533 16.759467 8.942933 23.364266 15.6672 6.6048 6.741333 11.554133 15.223467 14.848 25.429333 3.310933 10.222933 3.7888 22.528 1.4336 36.9152-0.955733 3.720533-2.833067 12.9024-5.666133 27.528534s-6.144 31.453867-9.898667 50.500266a1786.197333 1786.197333 0 0 1-12.7488 58.862934 952.661333 952.661333 0 0 1-13.448533 51.882666c-2.3552 8.362667-5.7856 16.964267-10.257067 25.770667a96.375467 96.375467 0 0 1-17.3568 24.046933 87.2448 87.2448 0 0 1-25.463466 17.749334c-9.915733 4.6592-21.7088 6.980267-35.396267 6.980266H312.456533c-9.898667 0-20.1728-2.082133-30.788266-6.263466a103.133867 103.133867 0 0 1-29.354667-17.7664 91.869867 91.869867 0 0 1-21.947733-27.869867c-5.666133-10.922667-8.4992-23.108267-8.4992-36.573867v-298.837333c0-28.330667 7.7824-50.517333 23.364266-66.525867C260.778667 281.088 282.7264 273.066667 311.04 273.066667H659.285333c10.376533 0 21.111467 1.979733 32.2048 5.922133 11.093333 3.9424 21.111467 9.403733 30.071467 16.384 8.977067 6.946133 16.2816 15.069867 21.947733 24.3712 5.666133 9.284267 8.4992 19.268267 8.4992 29.952v7.662933h-36.8128c-18.875733 0-40.925867-0.119467-66.167466-0.341333-25.258667-0.238933-52.138667-0.3584-80.6912-0.3584-28.552533 0-55.210667-0.119467-79.9744-0.341333-24.7808-0.238933-46.1312-0.341333-64.0512-0.341334h-32.5632c-12.270933 0-21.828267 3.822933-28.672 11.485867-6.826667 7.662933-12.151467 17.749333-15.9232 30.293333-3.754667 13.482667-8.021333 27.7504-12.731734 42.837334-4.727467 15.104-8.96 29.149867-12.7488 42.154666-4.7104 15.325867-9.437867 30.173867-14.148266 44.578134a38.570667 38.570667 0 0 0-1.416534 9.045333c0 7.901867 2.7136 14.506667 8.1408 19.8656 5.4272 5.341867 12.151467 8.021333 20.1728 8.021333 14.626133 0 24.5248-9.0624 29.730134-27.1872l37.512533-135.133866c61.3376 0.4608 117.486933 0.682667 168.448 0.682666h198.161067z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(255,255,255)'}' /%3E%3Cpath d='M699.733333 699.733333m-187.733333 0a187.733333 187.733333 0 1 0 375.466667 0 187.733333 187.733333 0 1 0-375.466667 0Z' fill='${(isStr ? colors : colors?.[2]) || 'rgb(188,231,254)'}' /%3E%3Cpath d='M716.8 614.4l159.812267 148.394667a188.245333 188.245333 0 0 1-117.2992 115.029333L614.4 716.8l85.333333-17.066667 17.066667-85.333333z' fill='${(isStr ? colors : colors?.[3]) || 'rgb(156,218,253)'}' /%3E%3Cpath d='M716.8 614.4v68.266667h68.266667v34.133333h-68.266667v68.266667h-34.133333v-68.266667h-68.266667v-34.133333h68.266667v-68.266667h34.133333z' fill='${(isStr ? colors : colors?.[4]) || 'rgb(255,255,255)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-shezhi */}
|
||||
|
||||
{ name === 'icon-shezhi' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M512 21.333333l424.938667 245.333334v490.666666L512 1002.666667 87.061333 757.333333v-490.666666L512 21.333333z m0 98.538667l-339.605333 196.053333V708.053333L512 904.106667l339.584-196.053334V315.925333L512 119.872zM512 341.333333a170.666667 170.666667 0 1 1 0 341.333334 170.666667 170.666667 0 0 1 0-341.333334z m0 85.333334a85.333333 85.333333 0 1 0 0 170.666666 85.333333 85.333333 0 0 0 0-170.666666z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(46,47,50)'}' opacity='.8' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-tishi */}
|
||||
|
||||
{ name === 'icon-tishi' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M512 64c247.424 0 448 200.576 448 448s-200.576 448-448 448S64 759.424 64 512 264.576 64 512 64z m0 64C299.936 128 128 299.936 128 512s171.936 384 384 384 384-171.936 384-384S724.064 128 512 128z m29.248 556.896V752h-64.32v-67.104h64.32zM515.712 272c42.464 0 76.48 12.096 101.984 36.288 25.536 24.192 38.304 55.104 38.304 92.736 0 22.816-4.672 41.28-14.08 55.488-9.344 14.208-28.256 35.072-56.704 62.592-20.704 20-34.112 36.928-40.256 50.784-6.144 13.888-9.216 34.368-9.216 61.44h-57.536c0-30.72 3.68-55.52 11.008-74.336 7.328-18.816 23.36-40.384 48.16-64.64l25.856-25.504c7.744-7.328 14.016-14.944 18.752-22.912 8.64-13.984 12.928-28.48 12.928-43.52 0-21.12-6.304-39.36-18.912-54.88-12.608-15.456-33.44-23.2-62.56-23.2-35.968 0-60.864 13.312-74.656 40-7.744 14.816-12.16 36.224-13.248 64.192H368c0-46.464 13.12-83.84 39.424-112.096 26.304-28.288 62.4-42.432 108.288-42.432z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.6' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-erweima */}
|
||||
|
||||
{ name === 'icon-erweima' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M362.666667 64a42.666667 42.666667 0 0 1 42.666666 42.666667v256a42.666667 42.666667 0 0 1-42.666666 42.666666H106.666667a42.666667 42.666667 0 0 1-42.666667-42.666666V106.666667a42.666667 42.666667 0 0 1 42.666667-42.666667h256z m-21.333334 64H128v213.333333h213.333333V128z m21.333334 512a42.666667 42.666667 0 0 1 42.666666 42.666667v256a42.666667 42.666667 0 0 1-42.666666 42.666666H106.666667a42.666667 42.666667 0 0 1-42.666667-42.666666V682.666667a42.666667 42.666667 0 0 1 42.666667-42.666667h256z m-21.333334 64H128v213.333333h213.333333V704z m181.333334-640A32 32 0 0 1 554.666667 96v277.333333a32 32 0 0 1-64 0v-277.333333A32 32 0 0 1 522.666667 64z m128 576a32 32 0 0 1 32 32v277.333333a32 32 0 0 1-64 0v-277.333333a32 32 0 0 1 32-32z m149.333333 0a32 32 0 0 1 32 32v277.333333a32 32 0 0 1-64 0v-277.333333a32 32 0 0 1 32-32z m149.333333 0a32 32 0 0 1 32 32v277.333333a32 32 0 0 1-64 0v-277.333333a32 32 0 0 1 32-32z m-853.333333-149.333333h853.333333a32 32 0 0 1 0 64h-853.333333a32 32 0 0 1 0-64zM938.666667 64a42.666667 42.666667 0 0 1 42.666666 42.666667v256a42.666667 42.666667 0 0 1-42.666666 42.666666H682.666667a42.666667 42.666667 0 0 1-42.666667-42.666666V106.666667a42.666667 42.666667 0 0 1 42.666667-42.666667h256z m-21.333334 64H704v213.333333h213.333333V128z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(45,39,57)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-dianjishoucang */}
|
||||
|
||||
{ name === 'icon-dianjishoucang' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M440.2176 108.9024a79.8208 79.8208 0 0 1 143.5392 0l96.3072 196.352a16.0256 16.0256 0 0 0 12.0576 8.832l215.3472 31.488a80.4608 80.4608 0 0 1 67.6864 91.264 80.7168 80.7168 0 0 1-23.3472 46.08l-155.8016 152.832-44.6976-46.1312 155.8272-152.832a16.128 16.128 0 0 0-8.8832-27.4688l-215.3472-31.488a80.0768 80.0768 0 0 1-60.2624-44.032l-96.2816-196.352a15.9744 15.9744 0 0 0-28.6976 0l-96.3328 196.352a80.0768 80.0768 0 0 1-60.2624 44.032l-215.3472 31.488a16.1792 16.1792 0 0 0-8.8832 27.4688l155.8528 152.832a80.8448 80.8448 0 0 1 23.0144 71.296l-36.7872 215.808a16.2048 16.2048 0 0 0 1.6128 10.24c4.096 7.8592 13.7984 10.88 21.6064 6.7328l192.6144-101.888 29.7984 57.0368-192.6144 101.888a79.7952 79.7952 0 0 1-108.0832-33.792 80.9728 80.9728 0 0 1-8.0384-51.0976l36.7872-215.808a16.1792 16.1792 0 0 0-4.608-14.2592l-155.8272-152.832a80.896 80.896 0 0 1-1.4336-113.92 79.872 79.872 0 0 1 45.7984-23.4752l215.3472-31.488a16.0256 16.0256 0 0 0 12.032-8.8064l96.3072-196.352z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.8' /%3E%3Cpath d='M576 784h288v64H576z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(0,0,0)'}' opacity='.8' /%3E%3Cpath d='M688 960V672h64V960z' fill='${(isStr ? colors : colors?.[2]) || 'rgb(0,0,0)'}' opacity='.8' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-gouwuche */}
|
||||
|
||||
{ name === 'icon-gouwuche' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M288 816m64 0l0 0q64 0 64 64l0 0q0 64-64 64l0 0q-64 0-64-64l0 0q0-64 64-64Z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(68,68,68)'}' /%3E%3Cpath d='M696 816m64 0l0 0q64 0 64 64l0 0q0 64-64 64l0 0q-64 0-64-64l0 0q0-64 64-64Z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(68,68,68)'}' /%3E%3Cpath d='M167.765333 152c27.52 0 50.965333 19.989333 55.296 47.168l16.981334 106.432h633.898666c2.133333 0 4.288 0.128 6.421334 0.362667l3.2 0.469333a56 56 0 0 1 45.546666 64.768l-62.378666 358.4a56 56 0 0 1-55.168 46.4h-497.28a56 56 0 0 1-55.296-47.168L175.658667 206.72a8 8 0 0 0-7.893334-6.741333H80a24 24 0 0 1 0-48h87.765333z m138.602667 569.258667a8 8 0 0 0 7.893333 6.741333h497.28a8 8 0 0 0 7.893334-6.613333l62.4-358.4a8 8 0 0 0-6.506667-9.258667l-0.682667-0.106667-626.944-0.021333 58.666667 367.658667z' fill='${(isStr ? colors : colors?.[2]) || 'rgb(68,68,68)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-shoucangchenggong */}
|
||||
|
||||
{ name === 'icon-shoucangchenggong' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M456.8064 119.6288a75.392 75.392 0 0 1 135.9872 0l91.4944 187.6736c3.6608 7.552 10.7776 12.8 19.0208 14.0032l204.544 30.1056c41.472 6.0928 70.1696 45.056 64.1536 87.04a77.1328 77.1328 0 0 1-22.1184 43.9296l-137.1648 135.3728-137.7792 130.7136-93.6192-93.824a25.6 25.6 0 0 0-36.2496 36.1728l111.2832 111.488a25.6 25.6 0 0 0 35.7376 0.512l110.4384-104.8064 27.008 159.4112c6.8352 40.2944-18.688 78.6432-57.5488 87.7568l-4.352 0.896a75.008 75.008 0 0 1-48.128-7.7056L536.576 840.96a25.0112 25.0112 0 0 0-23.5264 0l-182.9632 97.408a75.3664 75.3664 0 0 1-102.4-32.256 77.6192 77.6192 0 0 1-7.6032-48.6912l34.9184-206.2848a25.8048 25.8048 0 0 0-7.2704-22.656l-147.9936-146.0992A77.4656 77.4656 0 0 1 98.304 373.76a75.52 75.52 0 0 1 43.392-22.3744l204.544-30.1056a25.2928 25.2928 0 0 0 19.0464-14.0032z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(247,195,88)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-fenxiangshangpin */}
|
||||
|
||||
{ name === 'icon-fenxiangshangpin' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M542.976 112.896l-3.2 0.0768A64 64 0 0 0 478.976 176.896l-0.0256 117.7344-6.7328 2.176c-160.256 52.48-269.824 119.296-328.2688 202.24-52.992 75.2128-83.6352 180.5568-92.928 315.8272l-0.6656 10.752A64.0256 64.0256 0 0 0 110.4384 893.44c20.4032 1.2032 40.192-7.424 53.1712-23.2192 48.896-59.2896 96.4608-101.8624 142.2592-127.872l5.4272-2.9952c43.8784-23.3984 98.304-34.6112 163.5328-33.28l4.1216 0.1536v155.904a64 64 0 0 0 107.5712 46.8992l368.9728-342.6048a64 64 0 0 0 0-93.7984L586.496 129.9968a64 64 0 0 0-43.5456-17.1008z m0 64l368.9728 342.6304L542.976 862.1312v-186.1888c0-16.6912-12.8-30.5664-29.44-31.8976-95.232-7.7056-175.1552 6.272-239.2576 42.6496l-6.656 3.8656C218.7776 719.616 169.984 763.3152 120.8832 821.504l-6.656 7.9872 0.6656-10.3936c8.5248-124.3904 35.9936-218.7776 81.3824-283.1872 52.1728-74.0864 160-137.1392 324.0192-187.1616a32 32 0 0 0 22.656-30.6176V176.896z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(0,0,0)'}' opacity='.8' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-kefu */}
|
||||
|
||||
{ name === 'icon-kefu' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M512 152c162.133333 0 296.448 119.082667 320.256 274.56a84.138667 84.138667 0 0 1 79.744 84.010667v165.653333a84.138667 84.138667 0 0 1-84.138667 84.117333H796.16a84.138667 84.138667 0 0 1-84.138667-84.117333v-165.653333c0-42.24 31.146667-77.226667 71.701334-83.221334C760.746667 298.133333 647.829333 200 512 200c-135.829333 0-248.746667 98.133333-271.722667 227.370667a84.138667 84.138667 0 0 1 71.722667 83.2v165.653333a84.16 84.16 0 0 1-66.474667 82.261333 126.293333 126.293333 0 0 0 116.736 78.037334h69.866667a83.370667 83.370667 0 0 1 163.136 20.330666l0.064 3.818667a83.328 83.328 0 0 1-163.2 23.850667h-69.866667a174.336 174.336 0 0 1-165.269333-118.826667l-1.706667-5.376-3.477333-0.085333a84.138667 84.138667 0 0 1-79.808-84.010667v-165.653333a84.138667 84.138667 0 0 1 79.786667-84.032C215.573333 271.082667 349.866667 152 512 152z m0 673.045333c-18.666667 0-33.941333 14.464-35.242667 32.810667l-0.085333 2.816a35.328 35.328 0 0 0 70.570667 2.517333l0.085333-2.816c0-19.52-15.808-35.328-35.328-35.328z m324.010667-349.696v1.173334h-48l-0.021334-1.173334a36.138667 36.138667 0 0 0-27.989333 35.2v165.674667c0 19.946667 16.170667 36.117333 36.138667 36.117333h31.722666c19.968 0 36.138667-16.170667 36.138667-36.117333v-165.653333c0-17.152-11.946667-31.530667-27.989333-35.2zM160 510.549333v165.674667c0 17.152 11.946667 31.530667 28.010667 35.2v-1.173333h48l0.021333 1.173333a36.138667 36.138667 0 0 0 27.968-35.2v-165.653333c0-17.152-11.946667-31.530667-27.989333-35.2v1.152h-48l-0.021334-1.173334a36.138667 36.138667 0 0 0-27.989333 35.2z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(68,68,68)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-xinzenganniu */}
|
||||
|
||||
{ name === 'icon-xinzenganniu' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M0 0m341.333333 0l341.333334 0q341.333333 0 341.333333 341.333333l0 341.333334q0 341.333333-341.333333 341.333333l-341.333334 0q-341.333333 0-341.333333-341.333333l0-341.333334q0-341.333333 341.333333-341.333333Z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(51,127,255)'}' /%3E%3Cpath d='M512 256a32 32 0 0 1 32 32l-0.021333 192H736a32 32 0 0 1 0 64h-192.021333l0.021333 192a32 32 0 0 1-64 0l-0.021333-192H288a32 32 0 0 1 0-64h191.978667l0.021333-192A32 32 0 0 1 512 256z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(255,255,255)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-jianshaoanniu */}
|
||||
|
||||
{ name === 'icon-jianshaoanniu' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M675.84 10.24H348.16C161.52576 10.24 10.24 161.52576 10.24 348.16v327.68c0 186.63424 151.28576 337.92 337.92 337.92h327.68c186.63424 0 337.92-151.28576 337.92-337.92V348.16C1013.76 161.52576 862.47424 10.24 675.84 10.24z m0 20.48c175.3088 0 317.44 142.1312 317.44 317.44v327.68c0 175.3088-142.1312 317.44-317.44 317.44H348.16C172.8512 993.28 30.72 851.1488 30.72 675.84V348.16C30.72 172.8512 172.8512 30.72 348.16 30.72h327.68z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(51,127,255)'}' /%3E%3Cpath d='M296.96 481.28m30.72 0l368.64 0q30.72 0 30.72 30.72l0 0q0 30.72-30.72 30.72l-368.64 0q-30.72 0-30.72-30.72l0 0q0-30.72 30.72-30.72Z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(51,127,255)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-daifahuo2 */}
|
||||
|
||||
{ name === 'icon-daifahuo2' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M864 416a32 32 0 0 1 32 32v416a32 32 0 0 1-32 32H160a32 32 0 0 1-32-32V448a32 32 0 0 1 32-32h704z m-80 320H528a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h256a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z m0-128H608a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h176a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(64,123,244)'}' /%3E%3Cpath d='M748.8 192a32 32 0 0 1 28.24 16.944L896 432v16a32 32 0 0 0-32-32H160a32 32 0 0 0-32 32v-16l118.96-223.056A32 32 0 0 1 275.2 192h473.6z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(142,186,251)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-daishouhuo2 */}
|
||||
|
||||
{ name === 'icon-daishouhuo2' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M904 240a32 32 0 0 1 32 32v541.152a32 32 0 0 1-32 32h-79.76a114.016 114.016 0 0 0-111.248-88.88 114.016 114.016 0 0 0-111.232 88.864H416.24a114.016 114.016 0 0 0-111.248-88.864 114.016 114.016 0 0 0-111.232 88.864H128a32 32 0 0 1-32-32V535.472a32 32 0 0 1 6.656-19.52l133.744-173.6a32 32 0 0 1 25.344-12.48H456V272a32 32 0 0 1 32-32h416zM712.992 804.272a66.016 66.016 0 0 1 61.088 40.864h-122.16a66.016 66.016 0 0 1 61.088-40.864z m-408 0a66.016 66.016 0 0 1 61.088 40.864h-122.16a66.016 66.016 0 0 1 61.088-40.864z m61.008-388.48h-36.016a36 36 0 0 0-28.784 14.368l-107.92 143.68a36 36 0 0 0 28.8 57.6h143.92a36 36 0 0 0 36-36v-143.664a36 36 0 0 0-36-36z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(64,123,244)'}' /%3E%3Cpath d='M305.008 804.272a65.92 65.92 0 0 1 66 65.872 65.92 65.92 0 0 1-66 65.856 65.92 65.92 0 0 1-66-65.856 65.92 65.92 0 0 1 65.984-65.872zM713.008 804.272a65.92 65.92 0 0 1 65.984 65.872 65.92 65.92 0 0 1-65.984 65.856 65.92 65.92 0 0 1-66.016-65.856 65.92 65.92 0 0 1 66.016-65.872z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(142,186,251)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-tuikuan-shouhou */}
|
||||
|
||||
{ name === 'icon-tuikuan-shouhou' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M848 384a32 32 0 0 1 32 32v448a32 32 0 0 1-32 32H176a32 32 0 0 1-32-32V416a32 32 0 0 1 32-32h672z m-376.448 112H384l11.264 13.312 68.608 132.608h-71.168l-6.656 48.64h77.312l-13.312 95.232h77.824l13.312-95.232h77.824l6.656-48.64h-71.168L670.72 496h-83.504l-71.12 98.816L471.552 496z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(64,123,244)'}' opacity='.95' /%3E%3Cpath d='M335.536 148.56a32 32 0 0 1 35.12 53.44l-2.192 1.44L307.488 240H832a32 32 0 0 1 31.92 29.6L864 272a32 32 0 0 1-29.6 31.92L832 304H192c-31.616 0-43.68-40.576-18.528-58.112l2.064-1.328 160-96z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(142,186,251)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-daipeibu2 */}
|
||||
|
||||
{ name === 'icon-daipeibu2' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M864 496v317.088A34.912 34.912 0 0 1 829.088 848H290.912A34.912 34.912 0 0 1 256 813.088V496h608zM256 274.912c0-19.28 15.632-34.912 34.912-34.912h538.176c19.28 0 34.912 15.632 34.912 34.912V432H256v-157.088z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(64,123,244)'}' /%3E%3Cpath d='M240 144a16 16 0 0 1 16 16v668.112c7.84 5.28 14.624 12.032 19.888 19.888H864a32 32 0 0 1 32 32v16a32 32 0 0 1-32 32H275.872A72 72 0 1 1 176 828.144V224L128 224a16 16 0 0 1-16-16v-48a16 16 0 0 1 16-16h112z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(142,186,251)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
{/* icon-daifukuan2 */}
|
||||
|
||||
{ name === 'icon-daifukuan2' && (<View style={{backgroundImage: `url(${quot}data:image/svg+xml, %3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='${svgSize}px' height='${svgSize}px'%3E%3Cpath d='M848 368a32 32 0 0 1 32 32v448a32 32 0 0 1-32 32H176a32 32 0 0 1-32-32V400a32 32 0 0 1 32-32h672zM512 688H240a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h272a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z' fill='${(isStr ? colors : colors?.[0]) || 'rgb(64,123,244)'}' /%3E%3Cpath d='M765.664 216.496L812 368H160.688l565.024-172.736a32 32 0 0 1 39.952 21.248z' fill='${(isStr ? colors : colors?.[1]) || 'rgb(142,186,251)'}' /%3E%3C/svg%3E${quot})`, width: `${svgSize}px`, height: `${svgSize}px`, ...customStyle}} className={classnames("icon", customClassName)} />) }
|
||||
|
||||
</Block>
|
||||
)
|
||||
}
|
||||
|
||||
export default IconFont
|
||||
18
src/components/layoutBlock/index.module.scss
Normal file
18
src/components/layoutBlock/index.module.scss
Normal file
@ -0,0 +1,18 @@
|
||||
.layoutBlock {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
background-color: #fff;
|
||||
padding: 32px;
|
||||
margin-bottom: 20px;
|
||||
margin-left: 24px;
|
||||
margin-right: 24px;
|
||||
&--row {
|
||||
flex-flow: row nowrap;
|
||||
}
|
||||
&--col {
|
||||
flex-flow: column nowrap;
|
||||
}
|
||||
&--circle {
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
43
src/components/layoutBlock/index.tsx
Normal file
43
src/components/layoutBlock/index.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { Button, Radio, View } from '@tarojs/components'
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
type FlexDirection = 'row' | 'col'
|
||||
|
||||
interface PropsType {
|
||||
flexDirection?: FlexDirection
|
||||
onClick?: Function
|
||||
circle?: boolean
|
||||
children?: ReactNode
|
||||
customStyle?: React.CSSProperties
|
||||
customClassName?: string
|
||||
}
|
||||
|
||||
const LayoutBlock: FC<PropsType> = (props) => {
|
||||
const { flexDirection = 'col', circle = false, children, customStyle = {}, customClassName = '', onClick } = props
|
||||
|
||||
const getClassName = () => {
|
||||
const classObject = {
|
||||
[styles['layoutBlock--circle']]: circle,
|
||||
[styles[`layoutBlock--${flexDirection}`]]: flexDirection,
|
||||
}
|
||||
return classObject
|
||||
}
|
||||
|
||||
const handleClick = (event) => {
|
||||
console.log('event==>', event)
|
||||
onClick && onClick()
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
className={classnames(styles.layoutBlock, getClassName(), customClassName)}
|
||||
style={customStyle}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{children}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
export default LayoutBlock
|
||||
104
src/components/normalButton/index.module.scss
Normal file
104
src/components/normalButton/index.module.scss
Normal file
@ -0,0 +1,104 @@
|
||||
.button {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0 30px;
|
||||
height: 72px;
|
||||
border: 1px solid $color_main;
|
||||
background-color: #fff;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
box-sizing: border-box;
|
||||
|
||||
&--normal {
|
||||
height: 72px;
|
||||
font-size: $font_size_medium;
|
||||
}
|
||||
&--small {
|
||||
height: 60px;
|
||||
font-size: $font_size_min;
|
||||
}
|
||||
&--disabled {
|
||||
opacity: $opacity-disabled;
|
||||
}
|
||||
// 按钮类型
|
||||
&--primary {
|
||||
border: 1px solid $color_main;
|
||||
background-color: $color_main;
|
||||
color: white;
|
||||
}
|
||||
&--danger {
|
||||
border: 1px solid $color_danger;
|
||||
background-color: $color_danger;
|
||||
color: white;
|
||||
}
|
||||
&--warning {
|
||||
border: 1px solid $color_warning;
|
||||
background-color: $color_warning;
|
||||
color: white;
|
||||
}
|
||||
&--info {
|
||||
border: 1px solid $color_info;
|
||||
background-color: $color_info;
|
||||
color: white;
|
||||
}
|
||||
&--round {
|
||||
border-radius: 50px;
|
||||
}
|
||||
&--circle {
|
||||
border-radius: 16px;
|
||||
}
|
||||
// 朴素按钮
|
||||
&--plain {
|
||||
background-color: white;
|
||||
&.button--primary {
|
||||
border: 1px solid $color_main;
|
||||
color: $color_main;
|
||||
}
|
||||
&.button--danger {
|
||||
border: 1px solid $color_danger;
|
||||
color: $color_danger;
|
||||
}
|
||||
&.button--warning {
|
||||
border: 1px solid $color_warning;
|
||||
color: $color_warning;
|
||||
}
|
||||
&.button--info {
|
||||
border: 1px solid $color_info;
|
||||
color: $color_info;
|
||||
}
|
||||
}
|
||||
&--text {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
color: currentColor;
|
||||
.loading {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
left: -40px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
// active 伪类
|
||||
&--primary:active {
|
||||
background-color: rgba($color: $color_main, $alpha: 0.5);
|
||||
color: #fff;
|
||||
}
|
||||
&--danger:active {
|
||||
background-color: rgba($color: $color_danger, $alpha: 0.5);
|
||||
color: #fff;
|
||||
}
|
||||
&--warning:active {
|
||||
background-color: rgba($color: $color_warning, $alpha: 0.5);
|
||||
color: #fff;
|
||||
}
|
||||
&--info:active {
|
||||
background-color: rgba($color: $color_info, $alpha: 0.5);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
67
src/components/normalButton/index.tsx
Normal file
67
src/components/normalButton/index.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import { View } from '@tarojs/components'
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import Loading from '../loading'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
type ButtonType = 'primary' | 'danger' | 'warning' | 'info'
|
||||
type ButtonSize = 'normal' | 'small'
|
||||
|
||||
interface PropsType {
|
||||
size?: ButtonSize
|
||||
type?: ButtonType
|
||||
round?: boolean // 大圆角
|
||||
disabled?: boolean
|
||||
plain?: boolean // plain
|
||||
circle?: boolean // 小圆角
|
||||
children?: ReactNode
|
||||
onClick?: Function
|
||||
customClassName?: string
|
||||
customStyles?: React.CSSProperties
|
||||
customTextClassName?: string
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
const NormalButton: FC<PropsType> = (props) => {
|
||||
const {
|
||||
type = 'primary',
|
||||
size = 'normal',
|
||||
round = false,
|
||||
disabled = false,
|
||||
children,
|
||||
onClick,
|
||||
plain = false,
|
||||
circle = false,
|
||||
customStyles = {},
|
||||
customClassName = '',
|
||||
customTextClassName = '',
|
||||
loading = false,
|
||||
} = props
|
||||
const getClassName = () => {
|
||||
const classObject = {
|
||||
[styles['button--disabled']]: disabled,
|
||||
[styles[`button--${size}`]]: size,
|
||||
[styles[`button--${type}`]]: type,
|
||||
[styles['button--round']]: round,
|
||||
[styles['button--plain']]: plain,
|
||||
[styles['button--circle']]: circle,
|
||||
}
|
||||
return classObject
|
||||
}
|
||||
|
||||
const handleClick = (event) => {
|
||||
if (disabled) {
|
||||
return
|
||||
}
|
||||
onClick && onClick(event)
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={classnames(styles.button, getClassName(), customClassName)} style={customStyles} onClick={handleClick}>
|
||||
<View className={classnames(styles['button--text'], customTextClassName)}>
|
||||
<View className={styles.loading}>{loading && <Loading width={30} />}</View>
|
||||
{children}</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
export default NormalButton
|
||||
@ -7,12 +7,12 @@ import CloseBtnIcon from '@/components/closeBtn'
|
||||
|
||||
export interface Params {
|
||||
title?: string // 标题
|
||||
show?: false|true // 显示显示弹窗
|
||||
showTitle?: false|true // 是否显示标题
|
||||
show?: boolean // 显示显示弹窗
|
||||
showTitle?: boolean // 是否显示标题
|
||||
onClose?: () => void // 关闭事件
|
||||
children?: ReactNode // 插槽内容
|
||||
// IconButton?: ReactNode, //
|
||||
showIconButton?: false|true // 是否显示关闭按钮
|
||||
showIconButton?: boolean // 是否显示关闭按钮
|
||||
position?: 'bottom'|'top'|'right' // 弹出位置
|
||||
animationEnd?: () => void // 弹出动画结束
|
||||
}
|
||||
|
||||
78
src/components/searchBar/index.module.scss
Normal file
78
src/components/searchBar/index.module.scss
Normal file
@ -0,0 +1,78 @@
|
||||
.search_main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
z-index: 0;
|
||||
.icon_a_sousuo1_self {
|
||||
color: $color_font_two;
|
||||
}
|
||||
.search_con {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
justify-content: space-between;
|
||||
.input_bar {
|
||||
border-radius: 50px;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
flex: 1 1 auto;
|
||||
padding-left: 60px;
|
||||
background: #eee;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
input {
|
||||
flex: 1 1 auto;
|
||||
font-size: 27px;
|
||||
z-index: 0;
|
||||
&::-webkit-input-placeholder {
|
||||
/* WebKit browsers */
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&::-moz-placeholder {
|
||||
/* Mozilla Firefox 19+ */
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&::-ms-input-placeholder {
|
||||
/* Internet Explorer 10+ */
|
||||
color: #999;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
.search_closeBtn {
|
||||
margin: 0 15px;
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
width: 100px;
|
||||
font-size: $font_size_medium;
|
||||
color: $color_font_two;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.icon_inner {
|
||||
margin-right: 20px;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
margin-right: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
.icon_out {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.input_out {
|
||||
padding-left: 20px !important;
|
||||
}
|
||||
}
|
||||
.customRightSlot{
|
||||
margin-right: 20px;
|
||||
}
|
||||
127
src/components/searchBar/index.tsx
Normal file
127
src/components/searchBar/index.tsx
Normal file
@ -0,0 +1,127 @@
|
||||
import { View } from '@tarojs/components'
|
||||
import classnames from 'classnames'
|
||||
import type { ReactNode } from 'react'
|
||||
import { forwardRef, memo, useEffect, useImperativeHandle, useState } from 'react'
|
||||
import IconFont from '../iconfont/iconfont'
|
||||
import InputX from '../InputX/index'
|
||||
import styles from './index.module.scss'
|
||||
import CloseBtn from '@/components/closeBtn'
|
||||
|
||||
interface Params {
|
||||
clickOnSearch?: (val: string) => void
|
||||
disabled?: boolean
|
||||
placeholder?: string
|
||||
changeOnSearch?: (value: string) => void
|
||||
showIcon?: boolean
|
||||
placeIcon?: 'out' | 'inner'
|
||||
style?: Object
|
||||
showBtn?: boolean
|
||||
btnStyle?: Object
|
||||
btnTitle?: string
|
||||
defaultValue?: string
|
||||
children?: ReactNode
|
||||
customRightSlot?: ReactNode
|
||||
adjustPosition?: boolean
|
||||
showScan?: boolean
|
||||
handScan?: () => void
|
||||
cursorSpacing?: Number
|
||||
}
|
||||
const Search = (
|
||||
{
|
||||
clickOnSearch, // 点击筛选按钮触发
|
||||
changeOnSearch, // 输入文字触发
|
||||
adjustPosition = false,
|
||||
disabled = false, // 是否禁用
|
||||
placeholder = '输入搜索内容',
|
||||
showIcon = true, // 是否显示关闭图标
|
||||
showBtn = false, // 是否显示搜索按钮
|
||||
btnStyle = {},
|
||||
placeIcon = 'inner', // 搜索图标位置:inner在里面,out在外面
|
||||
btnTitle = '搜索', // 搜索文字
|
||||
defaultValue = '', // 默认值
|
||||
children,
|
||||
customRightSlot,
|
||||
showScan = false,
|
||||
handScan,
|
||||
cursorSpacing = 0,
|
||||
}: Params,
|
||||
ref,
|
||||
) => {
|
||||
const [inputCon, setInputCon] = useState('')
|
||||
useEffect(() => {
|
||||
setInputCon(defaultValue)
|
||||
}, [defaultValue])
|
||||
|
||||
const onInputEven = (e) => {
|
||||
const value = e.detail.value
|
||||
setInputCon(value)
|
||||
changeOnSearch?.(value)
|
||||
}
|
||||
|
||||
const clearInput = () => {
|
||||
setInputCon('')
|
||||
changeOnSearch?.('')
|
||||
}
|
||||
useImperativeHandle(ref, () => ({
|
||||
clearInput,
|
||||
}))
|
||||
const onSearch = () => {
|
||||
clickOnSearch?.(inputCon)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<View className={styles.search_main}>
|
||||
<View className={styles.search_con}>
|
||||
{showIcon && (
|
||||
<IconFont
|
||||
name="icon-sousuo"
|
||||
size={40}
|
||||
color="#bbbbbb"
|
||||
customClassName={classnames(styles.icon_a_sousuo1_self, placeIcon == 'inner' ? styles.icon_inner : styles.icon_out)}
|
||||
></IconFont>
|
||||
)}
|
||||
<View className={styles.input_bar}>
|
||||
<InputX
|
||||
cursorSpacing={cursorSpacing as any}
|
||||
adjustPosition={adjustPosition}
|
||||
placeholderStyle="color:#ABABAB; font-size:26rpx"
|
||||
onConfirm={onSearch}
|
||||
disabled={disabled}
|
||||
value={inputCon}
|
||||
placeholder={placeholder}
|
||||
onInput={e => onInputEven(e)}
|
||||
customClassName={classnames(placeIcon == 'out' && styles.input_out)}
|
||||
customStyle={{ width: '100%' }}
|
||||
/>
|
||||
<View className={styles.search_closeBtn}>
|
||||
{!!inputCon && <CloseBtn onClose={() => clearInput()} />}
|
||||
</View>
|
||||
{showScan && (
|
||||
<View
|
||||
onClick={() => {
|
||||
handScan?.()
|
||||
}}
|
||||
>
|
||||
<IconFont name="icon-gongnengtubiao-saomiao" size={40} color="#337FFF"></IconFont>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View className={styles.customRightSlot}>{customRightSlot}</View>
|
||||
</View>
|
||||
</View>
|
||||
{showBtn && (
|
||||
<View style={btnStyle} className={styles.btn} onClick={onSearch}>
|
||||
{btnTitle}
|
||||
</View>
|
||||
)}
|
||||
{children}
|
||||
</View>
|
||||
</>
|
||||
)
|
||||
}
|
||||
export default memo(
|
||||
forwardRef(
|
||||
Search,
|
||||
),
|
||||
)
|
||||
@ -1,36 +1,36 @@
|
||||
.other_desc{
|
||||
// padding: 0 20px;
|
||||
.other_desc {
|
||||
box-sizing: border-box;
|
||||
.title {
|
||||
font-size: $font_size;
|
||||
font-weight: 500;
|
||||
}
|
||||
.textarea {
|
||||
position: relative;
|
||||
height: 165.4px;
|
||||
.descDataNum {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
font-size: 22px;
|
||||
color: #ababab;
|
||||
}
|
||||
}
|
||||
.textarea_con,
|
||||
.textarea_con_pretend {
|
||||
background-color: #f3f3f3;
|
||||
border: 2px solid #e6e6e6;
|
||||
border-radius: 10px;
|
||||
width: 100%;
|
||||
font-size: 25px;
|
||||
height: 165.4px;
|
||||
padding: 20px 20px 30px 20px;
|
||||
box-sizing: border-box;
|
||||
.title{
|
||||
font-size: $font_size;
|
||||
font-weight: 700;
|
||||
}
|
||||
.textarea{
|
||||
position: relative;
|
||||
height: 165.4px;
|
||||
.descDataNum{
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
font-size: 22px;
|
||||
color: #ABABAB;
|
||||
}
|
||||
}
|
||||
.textarea_con, .textarea_con_pretend{
|
||||
background-color: #f3f3f3;
|
||||
border: 2px solid #e6e6e6;
|
||||
border-radius: 10px;
|
||||
width: 100%;
|
||||
font-size: 25px;
|
||||
height: 165.4px;
|
||||
padding: 20px 20px 30px 20px;
|
||||
box-sizing: border-box;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.textarea_con_pretend{
|
||||
color: $color_font_two;
|
||||
}
|
||||
.textarea_con_pretend_ed{
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
margin-top: 20px;
|
||||
}
|
||||
.textarea_con_pretend {
|
||||
color: $color_font_two;
|
||||
}
|
||||
.textarea_con_pretend_ed {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { Textarea, View } from '@tarojs/components'
|
||||
import { memo, useEffect, useMemo, useState } from 'react'
|
||||
import { memo, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import styles from './index.module.scss'
|
||||
import { usePropsValue } from '@/use/useCommon'
|
||||
|
||||
// 其他说明
|
||||
interface Param {
|
||||
@ -9,22 +10,32 @@ interface Param {
|
||||
onChange?: (val: string) => void
|
||||
placeholder?: string
|
||||
defaultValue?: string
|
||||
onlyRead?: false|true
|
||||
onlyRead?: boolean
|
||||
maxLength?: number
|
||||
customClassName?: string
|
||||
customStyle?: React.CSSProperties
|
||||
}
|
||||
const TextareaEnhance = ({ onChange, title = '', placeholder = '请输入', defaultValue, onlyRead = false }: Param) => {
|
||||
const [descData, setDescData] = useState({
|
||||
number: 0,
|
||||
value: '',
|
||||
count: 200,
|
||||
show: false,
|
||||
const TextareaEnhance = (props: Param) => {
|
||||
const { onChange: _onChange, title = '', placeholder = '请输入', defaultValue, onlyRead = false, maxLength = 200, customStyle, customClassName } = props
|
||||
const [number, setNumber] = useState(0)
|
||||
const [show, setShow] = useState(false)
|
||||
// 最大长度
|
||||
const countRef = useRef(maxLength)
|
||||
const [value, setValue] = usePropsValue({
|
||||
value: defaultValue,
|
||||
defaultValue: '',
|
||||
onChange: (res) => {
|
||||
_onChange?.(res)
|
||||
},
|
||||
})
|
||||
const getDesc = (value = '') => {
|
||||
let res = value
|
||||
if (value.length > descData.count) {
|
||||
res = value.slice(0, descData.count)
|
||||
if (value.length > countRef.current) {
|
||||
res = value.slice(0, countRef.current)
|
||||
}
|
||||
setDescData({ ...descData, number: res.length, value: res })
|
||||
onChange?.(res)
|
||||
setNumber(res.length)
|
||||
setValue(res)
|
||||
// setDescData({ ...descData, number: res.length, value: res })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -32,17 +43,18 @@ const TextareaEnhance = ({ onChange, title = '', placeholder = '请输入', defa
|
||||
}, [defaultValue])
|
||||
|
||||
const toggleShowRealTextarea = (show) => {
|
||||
setDescData({ ...descData, show })
|
||||
setShow(show)
|
||||
// setDescData({ ...descData, show })
|
||||
}
|
||||
return (
|
||||
<View className={styles.other_desc}>
|
||||
<View className={styles.title}>{title}</View>
|
||||
<View className={styles.textarea}>
|
||||
{(descData.show && !onlyRead)
|
||||
? <Textarea autoFocus value={descData.value} onBlur={() => toggleShowRealTextarea(false)} className={styles.textarea_con} cursorSpacing={100} maxlength={descData.count} onInput={e => getDesc(e.detail.value)}></Textarea>
|
||||
: <View className={classnames(styles.textarea_con_pretend, descData.value && styles.textarea_con_pretend_ed)} onClick={() => toggleShowRealTextarea(true)}>{descData.value || placeholder}</View>
|
||||
{(show && !onlyRead)
|
||||
? <Textarea autoFocus value={value} onBlur={() => toggleShowRealTextarea(false)} style={customStyle} className={classnames(styles.textarea_con, customClassName)} cursorSpacing={100} maxlength={countRef.current} onInput={e => getDesc(e.detail.value)}></Textarea>
|
||||
: <View className={classnames(styles.textarea_con_pretend, value && styles.textarea_con_pretend_ed, customClassName)} style={customStyle} onClick={() => toggleShowRealTextarea(true)}>{value || placeholder}</View>
|
||||
}
|
||||
<View className={styles.descDataNum}>{`${descData.number}/${descData.count}`}</View>
|
||||
<View className={styles.descDataNum}>{`${number}/${countRef.current}`}</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
|
||||
@ -1,59 +0,0 @@
|
||||
|
||||
.collection_main {
|
||||
padding: 0 20px;
|
||||
min-height: 100%;
|
||||
background-color: #F8F8F8;
|
||||
.search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.miconfont_con{
|
||||
padding: 0 20px;
|
||||
}
|
||||
.miconfont{
|
||||
font-size: 30px;
|
||||
color: #007AFF;
|
||||
border: 1px solid #007AFF;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.operation{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px 30px 0 30px;
|
||||
font-size: 26px;
|
||||
color: #707070;
|
||||
.operation_check{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
&::after{
|
||||
content: '';
|
||||
height: 45px;
|
||||
width: 1PX;
|
||||
background-color: #ccc;
|
||||
position: absolute;
|
||||
right: -30px;
|
||||
}
|
||||
Text{
|
||||
margin-left: 15px;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.operation_check_right{
|
||||
.operation_check_move{
|
||||
color: #707070;
|
||||
margin-right: 30px;
|
||||
}
|
||||
.operation_check_cancel{
|
||||
color: #007AFF;
|
||||
}
|
||||
}
|
||||
.class_list{
|
||||
margin-top: 30px;
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,148 +0,0 @@
|
||||
import { Text, View } from '@tarojs/components'
|
||||
import Taro, { useRouter } from '@tarojs/taro'
|
||||
import classnames from 'classnames'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import Product from '../components/product'
|
||||
import styles from './index.module.scss'
|
||||
import Search from '@/components/search'
|
||||
import { getFilterData } from '@/common/util'
|
||||
import { alert } from '@/common/common'
|
||||
import { DelFavoriteProductApi, DetailFavoriteProductApi, MoveFavoriteProductApi } from '@/api/favorite'
|
||||
import MCheckbox from '@/components/checkbox'
|
||||
import AddCollection from '@/components/addCollection'
|
||||
|
||||
const CollectionClass = () => {
|
||||
const router = useRouter()
|
||||
|
||||
// 获取收藏夹面料
|
||||
const { fetchData: fetchDataDetailFavoriteProduct } = DetailFavoriteProductApi()
|
||||
const [colorInfo, setColorInfo] = useState<any>({})
|
||||
|
||||
// 获取搜索数据
|
||||
const [searchData, setSearchData] = useState({ id: 0, code_or_name: '' })
|
||||
const getFavoriteInfo = async() => {
|
||||
const res = await fetchDataDetailFavoriteProduct(searchData)
|
||||
if (res.success) {
|
||||
Taro.setNavigationBarTitle({
|
||||
title: res.data.name,
|
||||
})
|
||||
setColorInfo(res.data)
|
||||
}
|
||||
}
|
||||
|
||||
const onSearch = useCallback((e) => {
|
||||
setSearchData(val => ({ ...val, code_or_name: e }))
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
const id = router.params.id || 0
|
||||
if (id) { setSearchData(e => ({ ...e, id: parseInt(id as string) })) }
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (searchData.id) { getFavoriteInfo() }
|
||||
}, [searchData])
|
||||
|
||||
const productList = useMemo(() => {
|
||||
return colorInfo.product_color_list
|
||||
}, [colorInfo])
|
||||
|
||||
// 获取选中的id
|
||||
const [ids, setIds] = useState<number[]>([])
|
||||
const getSelectIds = useCallback((val) => {
|
||||
setIds(() => val)
|
||||
}, [])
|
||||
|
||||
// 全选反选
|
||||
const [allSelectStatus, setAllSelectStatus] = useState(false)
|
||||
const [selectStatus, setSelectStatus] = useState<1 | 2 | 3>(3)
|
||||
useEffect(() => {
|
||||
if (colorInfo.product_color_list?.length) {
|
||||
if (ids.length == colorInfo.product_color_list.length) {
|
||||
setSelectStatus(1)
|
||||
setAllSelectStatus(true)
|
||||
}
|
||||
else if (ids.length > 0 && ids.length < colorInfo.product_color_list.length) {
|
||||
setSelectStatus(2)
|
||||
setAllSelectStatus(false)
|
||||
}
|
||||
else {
|
||||
setSelectStatus(3)
|
||||
setAllSelectStatus(false)
|
||||
}
|
||||
}
|
||||
}, [ids, colorInfo])
|
||||
|
||||
const [collectionShow, setCollectionShow] = useState(false)
|
||||
const closeCollection = useCallback(() => {
|
||||
setCollectionShow(false)
|
||||
}, [])
|
||||
const selectCallBack = useCallback(() => {
|
||||
setAllSelectStatus(() => true)
|
||||
setSelectStatus(1)
|
||||
}, [])
|
||||
const colseCallBack = useCallback(() => {
|
||||
setAllSelectStatus(() => false)
|
||||
setSelectStatus(3)
|
||||
}, [])
|
||||
// 移动面料
|
||||
const { fetchData: fetchDataMoveFavoriteProduct } = MoveFavoriteProductApi()
|
||||
const onAdd = async(val) => {
|
||||
if (ids.length == 0) { return alert.none('请选择要移动面料') }
|
||||
const res = await fetchDataMoveFavoriteProduct({
|
||||
source_favorite_id: searchData.id,
|
||||
target_favorite_id: val.id,
|
||||
product_id: ids,
|
||||
})
|
||||
if (res.success) {
|
||||
getFavoriteInfo()
|
||||
setCollectionShow(false)
|
||||
alert.success('修改成功')
|
||||
}
|
||||
}
|
||||
|
||||
// 取消收藏
|
||||
const { fetchData: delFavoriteProductFetchData } = DelFavoriteProductApi()
|
||||
const delCollectioin = async() => {
|
||||
if (ids.length == 0) { return alert.none('请选择要取消面料') }
|
||||
const showModalRes = await Taro.showModal({
|
||||
title: '是否要取消收藏',
|
||||
confirmText: '是',
|
||||
cancelText: '否',
|
||||
})
|
||||
if (showModalRes.confirm) {
|
||||
const res = await delFavoriteProductFetchData({ favorite_id: searchData.id, product_id: ids })
|
||||
if (res.success) {
|
||||
getFavoriteInfo()
|
||||
alert.none('已取消收藏')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View className={styles.collection_main}>
|
||||
<View className={styles.search}>
|
||||
<Search style={{ width: '100%' }} debounceTime={300} changeOnSearch={onSearch} placeholder="请输入面料关键词" />
|
||||
</View>
|
||||
<View className={styles.operation}>
|
||||
<View className={styles.operation_check}>
|
||||
<MCheckbox status={allSelectStatus} onSelect={() => selectCallBack()} onClose={() => colseCallBack()} />
|
||||
<Text className={styles.allSelect}>全选</Text>
|
||||
</View>
|
||||
<View className={styles.operation_check_right}>
|
||||
<Text className={styles.operation_check_move} onClick={() => setCollectionShow(true)}>
|
||||
移动到
|
||||
</Text>
|
||||
<Text className={styles.operation_check_cancel} onClick={delCollectioin}>
|
||||
取消收藏
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.class_list}>
|
||||
<Product productList={productList} onSelectIds={getSelectIds} selectStatus={selectStatus} openCheckBox />
|
||||
</View>
|
||||
<AddCollection show={collectionShow} onAdd={onAdd} onClose={closeCollection} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default CollectionClass
|
||||
@ -1,4 +1,4 @@
|
||||
export default {
|
||||
navigationBarTitleText: '收藏详情',
|
||||
enableShareAppMessage: true,
|
||||
}
|
||||
export default {
|
||||
navigationBarTitleText: '收藏详情',
|
||||
enableShareAppMessage: true,
|
||||
}
|
||||
79
src/pages/collection/collectionDetail/index.module.scss
Normal file
79
src/pages/collection/collectionDetail/index.module.scss
Normal file
@ -0,0 +1,79 @@
|
||||
.collection_con {
|
||||
display: flex;
|
||||
|
||||
flex-flow: column nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
background-color: #f7f7f7;
|
||||
.collectionContent {
|
||||
padding-top: 24px;
|
||||
width: 100%;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.title_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
.title {
|
||||
font-size: $font_size;
|
||||
font-weight: 500;
|
||||
}
|
||||
.select {
|
||||
flex: 1;
|
||||
height: 60px;
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 26px;
|
||||
.input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.desc_item {
|
||||
display: flex;
|
||||
.title {
|
||||
font-size: $font_size;
|
||||
font-weight: 500;
|
||||
padding-top: 20px;
|
||||
}
|
||||
.desc {
|
||||
margin-left: 20px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.toTopBar {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.toTopTitle {
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
}
|
||||
.toTopTips {
|
||||
font-size: 24px;
|
||||
color: #909090;
|
||||
}
|
||||
}
|
||||
.bottomBar {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
padding-top: 16px;
|
||||
padding-left: 48px;
|
||||
padding-right: 48px;
|
||||
padding-bottom: 16px;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
}
|
||||
193
src/pages/collection/collectionDetail/index.tsx
Normal file
193
src/pages/collection/collectionDetail/index.tsx
Normal file
@ -0,0 +1,193 @@
|
||||
import { Input, ScrollView, Switch, Text, View } from '@tarojs/components'
|
||||
import type { BaseEventOrig, SwitchProps } from '@tarojs/components'
|
||||
import Taro, { useDidShow, useRouter } from '@tarojs/taro'
|
||||
import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import styles from './index.module.scss'
|
||||
import Popup from '@/components/popup'
|
||||
import TextareaEnhance from '@/components/textareaEnhance'
|
||||
import { CreateFavoriteApi, DelFavoriteApi, UpdateFavoriteApi } from '@/api/favorite'
|
||||
import { alert } from '@/common/common'
|
||||
import NormalButton from '@/components/normalButton'
|
||||
import LayoutBlock from '@/components/layoutBlock'
|
||||
import Divider from '@/components/divider'
|
||||
|
||||
const CollectionDetail = () => {
|
||||
const router = useRouter()
|
||||
const [isEdit, setEditStatus] = useState(false)
|
||||
const [submitData, setSubmitData] = useState({
|
||||
name: '',
|
||||
remark: '',
|
||||
})
|
||||
const currentData = useRef<Record<string, any> | undefined>(undefined)
|
||||
|
||||
const getOtherReason = (val) => {
|
||||
setSubmitData(e => ({ ...e, remark: val }))
|
||||
}
|
||||
|
||||
const changeInput = (val) => {
|
||||
setSubmitData(e => ({ ...e, name: val.detail.value }))
|
||||
}
|
||||
|
||||
const [toTop, setToTop] = useState(false)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
console.log('isEdit', router.params.isEdit)
|
||||
Taro.setNavigationBarTitle({
|
||||
title: router.params.title as string,
|
||||
})
|
||||
const isEdit = JSON.parse(router.params.isEdit as string)
|
||||
if (isEdit) {
|
||||
console.log(router.params.editData)
|
||||
currentData.current = JSON.parse(router.params.editData as string)
|
||||
console.log('currentData', currentData.current)
|
||||
setSubmitData({
|
||||
name: currentData.current?.name,
|
||||
remark: currentData.current?.remark,
|
||||
})
|
||||
setToTop(currentData.current?.is_top)
|
||||
}
|
||||
else {
|
||||
currentData.current = undefined
|
||||
}
|
||||
setEditStatus(isEdit)
|
||||
}, [router.params])
|
||||
|
||||
// 编辑保存
|
||||
const { fetchData: updateFavoriteFetchData } = UpdateFavoriteApi()
|
||||
const handleEditSave = async() => {
|
||||
if (!submitData.name) { return alert.none('请输入收藏夹名称!') }
|
||||
const res = await updateFavoriteFetchData({ ...submitData, id: currentData.current?.id, is_top: toTop ? 2 : 1 })
|
||||
if (res.success) {
|
||||
alert.success('编辑成功')
|
||||
setTimeout(() => {
|
||||
Taro.navigateBack()
|
||||
}, 1000)
|
||||
}
|
||||
else {
|
||||
alert.error('编辑失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 新增
|
||||
const { fetchData } = CreateFavoriteApi()
|
||||
// 新增保存
|
||||
const handleAddSave = async() => {
|
||||
if (!submitData.name) { return alert.none('请输入收藏夹名称!') }
|
||||
const res = await fetchData({ ...submitData, is_top: toTop ? 1 : 0 })
|
||||
if (res.success) {
|
||||
alert.success('创建成功')
|
||||
setTimeout(() => {
|
||||
Taro.navigateBack()
|
||||
}, 1000)
|
||||
}
|
||||
else {
|
||||
alert.error('创建失败')
|
||||
}
|
||||
}
|
||||
// 取消
|
||||
const handleCancel = () => {
|
||||
Taro.navigateBack()
|
||||
}
|
||||
// 删除
|
||||
const { fetchData: delFetchData } = DelFavoriteApi()
|
||||
const handleDelete = () => {
|
||||
Taro.showModal({
|
||||
content: '确认删除当前收藏夹?',
|
||||
cancelText: '取消',
|
||||
confirmText: '确认删除',
|
||||
confirmColor: '#E42945',
|
||||
async success(res) {
|
||||
if (res.confirm) {
|
||||
const res = await delFetchData({ id: currentData.current?.id })
|
||||
if (res.success) {
|
||||
alert.success('删除成功')
|
||||
setTimeout(() => {
|
||||
Taro.navigateBack()
|
||||
}, 1000)
|
||||
}
|
||||
else {
|
||||
alert.error('删除失败')
|
||||
}
|
||||
}
|
||||
else if (res.cancel) {
|
||||
console.log('用户点击取消')
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
const handleChange = (e: BaseEventOrig<SwitchProps.onChangeEventDetail>) => {
|
||||
setToTop(e.detail.value)
|
||||
}
|
||||
return (
|
||||
<View className={styles.collection_con}>
|
||||
<View className={styles.collectionContent}>
|
||||
|
||||
<LayoutBlock circle>
|
||||
|
||||
<View className={styles.title_item}>
|
||||
<View className={styles.title}>标题名称<Text style={{ color: 'red' }}>*</Text></View>
|
||||
<View className={styles.select}>
|
||||
<Input
|
||||
placeholder="请输入文件夹名称"
|
||||
className={styles.input}
|
||||
alwaysEmbed
|
||||
cursorSpacing={100}
|
||||
onInput={changeInput}
|
||||
value={submitData?.name}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<Divider direction="horizontal" customStyles={{ margin: '24rpx 0' }}></Divider>
|
||||
<View className={styles.desc_item}>
|
||||
<View className={styles.title}>简介信息</View>
|
||||
<View className={styles.desc}>
|
||||
<TextareaEnhance customStyle={{ background: '#fff', border: 'none', padding: '0 20rpx', fontSize: '28rpx' }} defaultValue={submitData?.remark} onChange={getOtherReason} placeholder="请输入简介" />
|
||||
</View>
|
||||
</View>
|
||||
</LayoutBlock>
|
||||
<LayoutBlock circle>
|
||||
<View className={styles.toTopBar}>
|
||||
<View>
|
||||
<View className={styles.toTopTitle}>收藏夹置顶</View>
|
||||
<View className={styles.toTopTips}>提醒:会优先展示该收藏夹</View>
|
||||
</View>
|
||||
<Switch
|
||||
className={styles.switch}
|
||||
checked={toTop}
|
||||
color="#337fff"
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</View>
|
||||
</LayoutBlock>
|
||||
</View>
|
||||
{/* <View className={styles.btns_con}>
|
||||
<View className={styles.btns_two}>
|
||||
<View className={styles.verify_btn} onClick={() => onSubmit()}>
|
||||
确认
|
||||
</View>
|
||||
</View>
|
||||
</View> */}
|
||||
{
|
||||
isEdit
|
||||
? <View className={styles.bottomBar}>
|
||||
<NormalButton plain type="danger" customStyles={{ width: '45%' }} round onClick={handleDelete}>
|
||||
删除
|
||||
</NormalButton>
|
||||
<NormalButton type="primary" round customStyles={{ width: '45%' }} onClick={handleEditSave}>
|
||||
保存
|
||||
</NormalButton>
|
||||
</View>
|
||||
: <View className={styles.bottomBar}>
|
||||
<NormalButton plain type="primary" customStyles={{ width: '45%' }} round onClick={handleCancel}>
|
||||
取消
|
||||
</NormalButton>
|
||||
<NormalButton type="primary" round customStyles={{ width: '45%' }} onClick={handleAddSave}>
|
||||
保存
|
||||
</NormalButton>
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
export default CollectionDetail
|
||||
@ -1,66 +0,0 @@
|
||||
|
||||
.collection_con{
|
||||
padding: 20px;
|
||||
.title_item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
.title{
|
||||
font-size: $font_size;
|
||||
font-weight: 700;
|
||||
width: 60px;
|
||||
}
|
||||
.select{
|
||||
flex:1;
|
||||
height: 60px;
|
||||
border: 2px solid #e6e6e6;
|
||||
border-radius: 10px;
|
||||
margin-left: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20px;
|
||||
font-size: 26px;
|
||||
color: #000;
|
||||
.input{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.desc_item{
|
||||
display: flex;
|
||||
.title{
|
||||
font-size: $font_size;
|
||||
font-weight: 700;
|
||||
width: 60px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
.desc{
|
||||
margin-left: 20px;
|
||||
flex:1;
|
||||
}
|
||||
}
|
||||
.btns_con{
|
||||
width: 100%;
|
||||
bottom:0;
|
||||
box-sizing: border-box;
|
||||
margin-top: 50px;
|
||||
.btns_two{
|
||||
display: flex;
|
||||
height: 82px;
|
||||
font-size: $font_size_big;
|
||||
border-radius: 40px;
|
||||
margin-bottom: 20px;
|
||||
.verify_btn{
|
||||
flex:1;
|
||||
border-radius: 40px;
|
||||
background: #007aff;
|
||||
text-align: center;
|
||||
line-height: 82px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
import { Input, ScrollView, Text, View } from '@tarojs/components'
|
||||
import { memo, useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import styles from './index.module.scss'
|
||||
import Popup from '@/components/popup'
|
||||
import TextareaEnhance from '@/components/textareaEnhance'
|
||||
import { CreateFavoriteApi } from '@/api/favorite'
|
||||
import { alert } from '@/common/common'
|
||||
|
||||
// 原因选择
|
||||
interface ReasonInfoParam {
|
||||
show?: boolean // 显示
|
||||
onClose?: () => void // 关闭
|
||||
onSuccess?: (val: any) => void // 成功
|
||||
defaultValue?: {
|
||||
remark: string
|
||||
name: string
|
||||
} // 默认数据
|
||||
}
|
||||
const CreatePopup = ({ show = false, onClose, onSuccess, defaultValue }: ReasonInfoParam) => {
|
||||
const submitData = useRef({
|
||||
name: '',
|
||||
remark: '',
|
||||
})
|
||||
|
||||
const getOtherReason = (val) => {
|
||||
submitData.current.remark = val
|
||||
}
|
||||
|
||||
const changeInput = (val) => {
|
||||
submitData.current.name = val.detail.value
|
||||
}
|
||||
|
||||
const onSubmit = () => {
|
||||
onSuccess?.(submitData.current)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
submitData.current = { name: defaultValue?.name as string, remark: defaultValue?.remark as string }
|
||||
}, [defaultValue])
|
||||
return (
|
||||
<Popup show={show} title="新建收藏夹" onClose={onClose}>
|
||||
<View className={styles.collection_con}>
|
||||
<View className={styles.title_item}>
|
||||
<View className={styles.title}>名称</View>
|
||||
<View className={styles.select}>
|
||||
<Input
|
||||
placeholder="请输入文件夹名称"
|
||||
className={styles.input}
|
||||
alwaysEmbed
|
||||
cursorSpacing={100}
|
||||
onInput={changeInput}
|
||||
value={defaultValue?.name}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View className={styles.desc_item}>
|
||||
<View className={styles.title}>简介</View>
|
||||
<View className={styles.desc}>
|
||||
<TextareaEnhance defaultValue={defaultValue?.remark} onChange={getOtherReason} placeholder="请输入简介" />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className={styles.btns_con}>
|
||||
<View className={styles.btns_two}>
|
||||
<View className={styles.verify_btn} onClick={() => onSubmit()}>
|
||||
确认
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Popup>
|
||||
)
|
||||
}
|
||||
export default memo(CreatePopup)
|
||||
@ -0,0 +1,32 @@
|
||||
.collection_con {
|
||||
.collection_item {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
font-size: 26px;
|
||||
padding: 0px 32px;
|
||||
align-items: center;
|
||||
.collectionImage {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
background-color: #f6f6f6;
|
||||
border: 1px solid #dedede;
|
||||
border-radius: 5px;
|
||||
margin-right: 32px;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.miconfont {
|
||||
font-size: 36px;
|
||||
color: #007aff;
|
||||
}
|
||||
.text {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.scrollStyle {
|
||||
max-height: 60vh;
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
import { Input, ScrollView, Text, View } from '@tarojs/components'
|
||||
import { memo, useCallback, useMemo, useRef } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import styles from './index.module.scss'
|
||||
import Popup from '@/components/popup'
|
||||
import TextareaEnhance from '@/components/textareaEnhance'
|
||||
import { CreateFavoriteApi, MoveFavoriteProductApi } from '@/api/favorite'
|
||||
import { alert, goLink } from '@/common/common'
|
||||
import LabAndImg from '@/components/LabAndImg'
|
||||
import IconFont from '@/components/iconfont/iconfont'
|
||||
import Divider from '@/components/divider'
|
||||
|
||||
// 原因选择
|
||||
interface ReasonInfoParam {
|
||||
show?: boolean // 显示
|
||||
onClose?: () => void // 关闭
|
||||
collectionList: any[]
|
||||
ids?: any[]
|
||||
sourceId: number
|
||||
onSuccess?: () => void
|
||||
}
|
||||
const MoveCollectionPopup = (props: ReasonInfoParam) => {
|
||||
const {
|
||||
show = false, onClose, collectionList, ids, sourceId, onSuccess,
|
||||
} = props
|
||||
// 移动面料
|
||||
const { fetchData: fetchDataMoveFavoriteProduct } = MoveFavoriteProductApi()
|
||||
const handleMove = async(val) => {
|
||||
if (ids?.length == 0) { return alert.none('请选择要移动面料') }
|
||||
const res = await fetchDataMoveFavoriteProduct({
|
||||
source_favorite_id: sourceId,
|
||||
target_favorite_id: val.id,
|
||||
product_id: Array.from(ids!),
|
||||
})
|
||||
if (res.success) {
|
||||
onClose?.()
|
||||
onSuccess?.()
|
||||
alert.success('移动成功')
|
||||
}
|
||||
else {
|
||||
alert.error('移动失败')
|
||||
}
|
||||
}
|
||||
const handleNewCollection = () => {
|
||||
// 新建收藏夹
|
||||
goLink('/pages/collection/collectionDetail/index', { title: '新建收藏夹', isEdit: false, editData: null })
|
||||
}
|
||||
return (
|
||||
<Popup show={show} onClose={onClose} showTitle title="移动收藏夹" >
|
||||
<Divider direction="horizontal" customStyles={{ marginTop: '0px', marginBottom: '12px' }}></Divider>
|
||||
<ScrollView className={styles.scrollStyle} scrollY>
|
||||
<View className={styles.collection_con}>
|
||||
{
|
||||
collectionList.map((item, key) => (
|
||||
<>
|
||||
<View key={key} className={styles.collection_item} onClick={() => handleMove(item)}>
|
||||
<View className={styles.collectionImage}></View>
|
||||
<Text className={styles.text}>{item.name}</Text>
|
||||
</View>
|
||||
<Divider direction="horizontal" customStyles={{ margin: '12px 0' }}></Divider>
|
||||
</>
|
||||
))
|
||||
}
|
||||
<View className={styles.collection_item} onClick={handleNewCollection}>
|
||||
<View className={styles.collectionImage}>
|
||||
<IconFont name="icon-xinzengshoucangjia" size={40}></IconFont>
|
||||
</View>
|
||||
<Text className={styles.text}>新建收藏夹</Text>
|
||||
</View>
|
||||
<Divider direction="horizontal" customStyles={{ margin: '12px 0' }}></Divider>
|
||||
|
||||
</View>
|
||||
</ScrollView>
|
||||
</Popup>
|
||||
)
|
||||
}
|
||||
export default memo(MoveCollectionPopup)
|
||||
@ -1,89 +0,0 @@
|
||||
|
||||
.products_list{
|
||||
padding: 0 20px 20px 20px;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
}
|
||||
.products_item{
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
&:nth-child(n+2){
|
||||
margin-top: 16px;
|
||||
}
|
||||
.checkbox{
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
z-index: 999;
|
||||
}
|
||||
.item_img{
|
||||
width: 198px;
|
||||
height: 198px;
|
||||
position: relative;
|
||||
image{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.num{
|
||||
padding: 5px 10px 5px 20px;
|
||||
font-size: $font_size_min;
|
||||
position: absolute;
|
||||
right:0;
|
||||
bottom: 0;
|
||||
background: rgba($color: #000, $alpha: 0.3);
|
||||
border-radius: 36px 0px 10px 0px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.item_con{
|
||||
padding-left: 20px;
|
||||
font-size: $font_size;
|
||||
flex:1;
|
||||
.title{
|
||||
font-size: $font_size;
|
||||
color: #707070;
|
||||
text{
|
||||
color: $color_font_one;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.tag_list{
|
||||
display: flex;
|
||||
margin-top: 16px;
|
||||
flex-wrap: wrap;
|
||||
.tag, .tag_g{
|
||||
max-width: 260rpx;
|
||||
padding: 3px 10px;
|
||||
background-color: #CDE5FF;
|
||||
font-size: $font_size_min;
|
||||
border-radius: 5px;
|
||||
color: $color_main;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.tag_g{
|
||||
background-color: #FFE6CE;
|
||||
color: #EE7500;
|
||||
}
|
||||
}
|
||||
.introduce{
|
||||
font-size: $font_size_medium;
|
||||
color: $color_font_two;
|
||||
|
||||
}
|
||||
.des{
|
||||
font-size:$font_size_medium;
|
||||
color: #707070;
|
||||
margin-top: 16px;
|
||||
@include common_ellipsis($params:2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
import { Image, View } from '@tarojs/components'
|
||||
import Taro from '@tarojs/taro'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import styles from './index.module.scss'
|
||||
import { goLink } from '@/common/common'
|
||||
import { formatHashTag, formatImgUrl } from '@/common/fotmat'
|
||||
import LabAndImg from '@/components/LabAndImg'
|
||||
import MCheckbox from '@/components/checkbox'
|
||||
|
||||
interface Params {
|
||||
productList?: any[]
|
||||
onSelectIds?: (val: number[]) => void
|
||||
selectStatus?: 1|2|3 // 1全选,2不做处理,3全清空
|
||||
openCheckBox?: true|false // 是否开启选择
|
||||
}
|
||||
const Product = ({ productList, onSelectIds, selectStatus = 2, openCheckBox = false }: Params) => {
|
||||
const [list, setList] = useState<any[]>([])
|
||||
useEffect(() => {
|
||||
setList(() => productList || [])
|
||||
}, [productList])
|
||||
|
||||
useEffect(() => {
|
||||
if (list.length && selectStatus != 2) {
|
||||
list.forEach((item) => {
|
||||
item.check = (selectStatus == 1)
|
||||
})
|
||||
setList(() => [...list])
|
||||
}
|
||||
}, [selectStatus])
|
||||
// 选中和取消选中
|
||||
const onSelect = (item) => {
|
||||
item.check = true
|
||||
setList(() => ([...list]))
|
||||
}
|
||||
const onClose = (item) => {
|
||||
item.check = false
|
||||
setList(() => ([...list]))
|
||||
}
|
||||
const onChangeSelect = (item) => {
|
||||
if (item.check) {
|
||||
onClose(item)
|
||||
}
|
||||
else {
|
||||
onSelect(item)
|
||||
}
|
||||
}
|
||||
|
||||
// 监听数据变化
|
||||
useEffect(() => {
|
||||
const ids: number[] = []
|
||||
list.forEach((item) => {
|
||||
if (item.check) { ids.push(item.product_id) }
|
||||
})
|
||||
onSelectIds?.(ids)
|
||||
}, [list])
|
||||
|
||||
return (
|
||||
<View className={styles.products_list}>
|
||||
{list?.map((item, index) => {
|
||||
return <View key={index} className={styles.products_item} onClick={() => openCheckBox ? onChangeSelect(item) : goLink(`/pages/details/index?id=${item.product_id}`)}>
|
||||
{openCheckBox && <View className={styles.checkbox} onClick={e => e.stopPropagation()}>
|
||||
<MCheckbox status={item.check} onSelect={() => onSelect(item)} onClose={() => onClose(item)} />
|
||||
</View>}
|
||||
<View className={styles.item_img}>
|
||||
<LabAndImg value={{ lab: item.lab, rgb: item.rgb, texture_url: item.texture_url }} />
|
||||
<View className={styles.num}>{item.enable_product_color_count}色</View>
|
||||
</View>
|
||||
<View className={styles.item_con}>
|
||||
<View className={styles.title}><text>{formatHashTag(item.product_code, '')} </text>{item.product_name}</View>
|
||||
<View className={styles.tag_list}>
|
||||
<View className={styles.tag}>{item.width}</View>
|
||||
<View className={styles.tag_g}>{item.weight_density}</View>
|
||||
</View>
|
||||
<View className={styles.introduce}>{item.component}</View>
|
||||
</View>
|
||||
</View>
|
||||
})}
|
||||
<View className="common_safe_area_y"></View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default Product
|
||||
@ -0,0 +1,85 @@
|
||||
.products_list {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
}
|
||||
.products_item {
|
||||
padding: 24px 0;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.checkbox {
|
||||
margin-left: 24px;
|
||||
margin-right: 32px;
|
||||
}
|
||||
.item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.item_img {
|
||||
width: 144px;
|
||||
height: 144px;
|
||||
position: relative;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.num {
|
||||
padding: 5px 10px 5px 20px;
|
||||
font-size: $font_size_min;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba($color: #000, $alpha: 0.3);
|
||||
border-radius: 36px 0px 10px 0px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.item_con {
|
||||
padding-left: 20px;
|
||||
font-size: $font_size;
|
||||
flex: 1;
|
||||
.title {
|
||||
font-size: $font_size;
|
||||
color: #707070;
|
||||
text {
|
||||
color: $color_font_one;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.tag_list {
|
||||
display: flex;
|
||||
margin-top: 16px;
|
||||
flex-wrap: wrap;
|
||||
.tag,
|
||||
.tag_g {
|
||||
max-width: 260rpx;
|
||||
padding: 3px 10px;
|
||||
background-color: #cde5ff;
|
||||
font-size: $font_size_min;
|
||||
border-radius: 5px;
|
||||
color: $color_main;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.tag_g {
|
||||
background-color: #ffe6ce;
|
||||
color: #ee7500;
|
||||
}
|
||||
}
|
||||
.introduce {
|
||||
font-size: $font_size_medium;
|
||||
color: $color_font_two;
|
||||
}
|
||||
.des {
|
||||
font-size: $font_size_medium;
|
||||
color: #707070;
|
||||
margin-top: 16px;
|
||||
@include common_ellipsis($params: 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
83
src/pages/collection/components/productItem/index.tsx
Normal file
83
src/pages/collection/components/productItem/index.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import type { ITouchEvent } from '@tarojs/components'
|
||||
import { BaseEventOrig, Image, View } from '@tarojs/components'
|
||||
import Taro from '@tarojs/taro'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import styles from './index.module.scss'
|
||||
import { goLink } from '@/common/common'
|
||||
import { formatHashTag, formatImgUrl } from '@/common/fotmat'
|
||||
import LabAndImg from '@/components/LabAndImg'
|
||||
import MCheckbox from '@/components/checkbox'
|
||||
import Divider from '@/components/divider'
|
||||
import { usePropsValue } from '@/use/useCommon'
|
||||
|
||||
interface ProductItemPropsType {
|
||||
item?: any
|
||||
openCheckBox: boolean
|
||||
event: TaroGeneral.Events
|
||||
metaDataId: number // 收藏夹信息包括id
|
||||
onCheckedChange: (id: ProductItemPropsType['metaDataId'], item: ProductItemPropsType['metaDataId'], checked: boolean) => void
|
||||
filterChecked: (currentId: number, filter?: () => boolean) => number[]
|
||||
checked: boolean
|
||||
}
|
||||
export const ProductItem = (props: ProductItemPropsType) => {
|
||||
const {
|
||||
item, openCheckBox, event, metaDataId, onCheckedChange, checked,
|
||||
} = props
|
||||
|
||||
const handleClickItem = (e: ITouchEvent) => {
|
||||
e.stopPropagation()
|
||||
event.trigger('updateCurrentSelection', metaDataId)
|
||||
if (openCheckBox) {
|
||||
if (checked) {
|
||||
onCheckedChange(metaDataId, item.product_id, false)
|
||||
}
|
||||
else {
|
||||
onCheckedChange(metaDataId, item.product_id, true)
|
||||
}
|
||||
}
|
||||
else {
|
||||
goLink(`/pages/details/index?id=${item.product_id}`)
|
||||
}
|
||||
}
|
||||
const noop = (e: ITouchEvent) => {
|
||||
e.stopPropagation()
|
||||
}
|
||||
// 选中
|
||||
const handleSelect = () => {
|
||||
console.log(item)
|
||||
onCheckedChange(metaDataId, item.product_id, true)
|
||||
}
|
||||
// 未选中
|
||||
const handleClose = () => {
|
||||
onCheckedChange(metaDataId, item.product_id, false)
|
||||
}
|
||||
|
||||
return (
|
||||
<View onClick={handleClickItem}>
|
||||
<Divider direction="horizontal" customStyles={{ margin: '0' }}></Divider>
|
||||
<View className={styles.products_item}>
|
||||
{openCheckBox
|
||||
&& <View className={styles.checkbox} onClick={noop}>
|
||||
<MCheckbox round size="normal" status={checked} onSelect={handleSelect} onClose={handleClose} ></MCheckbox>
|
||||
</View>}
|
||||
<View className={styles.item}>
|
||||
<View className={styles.item_img}>
|
||||
<LabAndImg value={{ lab: item.lab, rgb: item.rgb, texture_url: item.texture_url }} />
|
||||
<View className={styles.num}>{item.enable_product_color_count}色</View>
|
||||
</View>
|
||||
<View className={styles.item_con}>
|
||||
<View className={styles.title}><text>{formatHashTag(item.product_code, '')} </text>{item.product_name}</View>
|
||||
<View className={styles.tag_list}>
|
||||
<View className={styles.tag}>{item.width}</View>
|
||||
<View className={styles.tag_g}>{item.weight_density}</View>
|
||||
</View>
|
||||
<View className={styles.introduce}>{item.component}</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProductItem
|
||||
@ -1,18 +0,0 @@
|
||||
|
||||
.collection_con{
|
||||
padding: 20px ;
|
||||
.collection_item{
|
||||
display: flex;
|
||||
font-size: 26px;
|
||||
padding: 30px 10px;
|
||||
border-bottom: 1PX solid #F3F3F3;
|
||||
align-items: center;
|
||||
.miconfont{
|
||||
font-size: 36px;
|
||||
color: #007AFF;
|
||||
}
|
||||
.text{
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
import { Input, ScrollView, Text, View } from '@tarojs/components'
|
||||
import { memo, useCallback, useMemo, useRef } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import styles from './index.module.scss'
|
||||
import Popup from '@/components/popup'
|
||||
import TextareaEnhance from '@/components/textareaEnhance'
|
||||
import { CreateFavoriteApi } from '@/api/favorite'
|
||||
import { alert } from '@/common/common'
|
||||
|
||||
// 原因选择
|
||||
interface ReasonInfoParam {
|
||||
show?: boolean // 显示
|
||||
onClose?: () => void // 关闭
|
||||
onUpdate?: () => void // 编辑
|
||||
onBatchManagement?: () => void // 批量管理
|
||||
onDelete?: () => void // 删除
|
||||
|
||||
}
|
||||
const UpdatePopup = ({ show = false, onClose, onUpdate, onBatchManagement, onDelete }: ReasonInfoParam) => {
|
||||
const onClickEven = (val) => {
|
||||
if (val == 1) {
|
||||
onUpdate?.()
|
||||
}
|
||||
else if (val == 2) {
|
||||
onBatchManagement?.()
|
||||
}
|
||||
else {
|
||||
onDelete?.()
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Popup show={show} onClose={onClose} showTitle={false} >
|
||||
<View className={styles.collection_con}>
|
||||
<View className={styles.collection_item} onClick={() => onClickEven(1)}>
|
||||
<Text className={classnames(styles.miconfont, 'iconfont icon-bianji')}></Text>
|
||||
<Text className={styles.text}>编辑收藏夹</Text>
|
||||
</View>
|
||||
<View className={styles.collection_item} onClick={() => onClickEven(2)}>
|
||||
<Text className={classnames(styles.miconfont, 'iconfont icon-fenlei')}></Text>
|
||||
<Text className={styles.text}>批量管理</Text>
|
||||
</View>
|
||||
<View className={styles.collection_item} onClick={() => onClickEven(3)}>
|
||||
<Text className={classnames(styles.miconfont, 'iconfont icon-shanchu')}></Text>
|
||||
<Text className={styles.text}>删除该收藏夹</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Popup>
|
||||
)
|
||||
}
|
||||
export default memo(UpdatePopup)
|
||||
@ -1,4 +1,4 @@
|
||||
export default {
|
||||
navigationBarTitleText: '我的收藏',
|
||||
navigationBarTitleText: '收藏夹',
|
||||
enableShareAppMessage: true,
|
||||
}
|
||||
|
||||
@ -1,61 +1,155 @@
|
||||
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
.collection_main {
|
||||
padding: 0 20px;
|
||||
min-height: 100%;
|
||||
background-color: #F8F8F8;
|
||||
.search {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
min-height: 100%;
|
||||
background-color: #f8f8f8;
|
||||
.collection_content {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
.search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #ffffff;
|
||||
padding: 8px 24px;
|
||||
border-bottom: 1px solid #ededed;
|
||||
.miconfont_con {
|
||||
padding: 0 20px;
|
||||
}
|
||||
.miconfont {
|
||||
font-size: 30px;
|
||||
color: #007aff;
|
||||
border: 1px solid #007aff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.layout {
|
||||
padding: 14px 24px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
&Block {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
margin-right: 24px;
|
||||
}
|
||||
.content {
|
||||
font-size: 28px;
|
||||
color: #000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
.scrollContent {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
transition: height 0.5s ease-in;
|
||||
overflow: hidden;
|
||||
.class_item {
|
||||
margin: 20px 0;
|
||||
}
|
||||
.class_title {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
.class_prefix {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.miconfont_con{
|
||||
padding: 0 20px;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
&_top {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
.miconfont{
|
||||
font-size: 30px;
|
||||
color: #007AFF;
|
||||
border: 1px solid #007AFF;
|
||||
border-radius: 50%;
|
||||
&_bottom {
|
||||
color: #a4a4a4;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
display: flex;
|
||||
color: #505050;
|
||||
font-weight: 500;
|
||||
font-size: 28px;
|
||||
@include common_ellipsis();
|
||||
}
|
||||
.iconfont_show {
|
||||
display: block;
|
||||
}
|
||||
.iconfont_hide {
|
||||
display: none;
|
||||
}
|
||||
.fg {
|
||||
padding: 0 10px;
|
||||
}
|
||||
.num,
|
||||
.fg {
|
||||
color: #707070;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
.class_list{
|
||||
margin-top: 30px;
|
||||
.class_item{
|
||||
margin: 20px 0;
|
||||
}
|
||||
.class_title{
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
.title{
|
||||
flex: 1;
|
||||
color: #000;
|
||||
font-weight: 700;
|
||||
font-size: 28px;
|
||||
padding: 0 20px;
|
||||
@include common_ellipsis();
|
||||
}
|
||||
.fg{
|
||||
padding: 0 10px;
|
||||
}
|
||||
.num, .fg{
|
||||
color: #707070;
|
||||
font-weight: normal;
|
||||
}
|
||||
.miconfont_left{
|
||||
font-size: 30px;
|
||||
color: #707070;
|
||||
}
|
||||
.miconfont_open{
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.miconfont_close {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.more{font-size: 26px;}
|
||||
|
||||
}
|
||||
.class_con{
|
||||
overflow: hidden;
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.class_con {
|
||||
overflow: hidden;
|
||||
transition: all 0.5s ease-in-out;
|
||||
.products_list > View:first-child {
|
||||
padding-top: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.flexBox {
|
||||
display: flex;
|
||||
margin-left: 24px;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.icon--manage--cancel {
|
||||
color: $color_main;
|
||||
}
|
||||
.bottomBar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: white;
|
||||
padding: 16px 24px;
|
||||
transition: transform 0.1s ease-in;
|
||||
transform: translateY(100%);
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
.bottomLeft {
|
||||
margin-left: 12px;
|
||||
}
|
||||
.bottomRight {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.showBottomBar {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.multipleCheckbox {
|
||||
color: #686868;
|
||||
display: flex;
|
||||
}
|
||||
.multipleCheckbox__text {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
@ -1,169 +1,345 @@
|
||||
import Taro, { useDidHide, useDidShow } from '@tarojs/taro'
|
||||
import Taro, { Events, useDidShow } from '@tarojs/taro'
|
||||
import { Text, View } from '@tarojs/components'
|
||||
import type { ITouchEvent } from '@tarojs/components'
|
||||
import classnames from 'classnames'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import Product from './components/product'
|
||||
import CreatePopup from './components/createPopup'
|
||||
import UpdatePopup from './components/updatePopup'
|
||||
import type { SetStateAction } from 'react'
|
||||
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import Product, { ProductItem } from './components/productItem'
|
||||
import styles from './index.module.scss'
|
||||
import Search from '@/components/search'
|
||||
import { getFilterData } from '@/common/util'
|
||||
import MoveCollectionPopup from './components/moveCollectionPopup'
|
||||
import InfiniteScroll from '@/components/infiniteScroll'
|
||||
import MCheckbox from '@/components/checkbox/index'
|
||||
import Search from '@/components/searchBar'
|
||||
import { dataLoadingStatus, getFilterData } from '@/common/util'
|
||||
import { alert, goLink } from '@/common/common'
|
||||
import { CreateFavoriteApi, DelFavoriteApi, FavoriteListApi, UpdateFavoriteApi } from '@/api/favorite'
|
||||
import { DelFavoriteProductApi, FavoriteListApi } from '@/api/favorite'
|
||||
import useLogin from '@/use/useLogin'
|
||||
import IconText from '@/components/iconText'
|
||||
import LayoutBlock from '@/components/layoutBlock'
|
||||
import IconFont from '@/components/iconfont/iconfont'
|
||||
import NormalButton from '@/components/normalButton'
|
||||
// 消息机制
|
||||
export const collectionEvents = new Events()
|
||||
// 勾选map
|
||||
export type CheckedMap = Record<number, Record<number, boolean>>
|
||||
|
||||
export default () => {
|
||||
interface CollectionItemPropsType {
|
||||
selectId: number
|
||||
item?: any
|
||||
isManageStatus: boolean
|
||||
checkedMap: CheckedMap
|
||||
onCheckedChange: (id: number, item: CollectionItemPropsType['item'], checked: boolean) => void
|
||||
filterChecked: (currentId: number, filter?: () => boolean) => number[]
|
||||
}
|
||||
const CollectionItem = (props: CollectionItemPropsType) => {
|
||||
const {
|
||||
item, isManageStatus, selectId, onCheckedChange, filterChecked, checkedMap,
|
||||
} = props
|
||||
|
||||
// 控制下拉上拉
|
||||
const [isOpen, setOpen] = useState(false)
|
||||
const changeOpenCon = () => {
|
||||
// 更新当前选中的收藏夹
|
||||
collectionEvents.trigger('updateCurrentSelection', item.id)
|
||||
setOpen(e => !e)
|
||||
}
|
||||
|
||||
// 编辑
|
||||
const handleEditCollection = (e: ITouchEvent, item: any) => {
|
||||
e.stopPropagation()
|
||||
const editData = {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
remark: item.remark,
|
||||
is_top: item.is_top,
|
||||
}
|
||||
goLink('/pages/collection/collectionDetail/index', { title: '编辑收藏夹', isEdit: true, editData: JSON.stringify(editData) })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log('selectId && item.id', selectId, item.id, isManageStatus)
|
||||
if (selectId !== item.id && isManageStatus) {
|
||||
setOpen(false)
|
||||
}
|
||||
}, [isManageStatus, selectId])
|
||||
|
||||
return <LayoutBlock circle customClassName={styles.layout} onClick={changeOpenCon}>
|
||||
<View className={styles.class_item}>
|
||||
<View key={item.id} className={styles.class_title}>
|
||||
<View className={styles.class_prefix}>
|
||||
<View className={styles.class_prefix_top}>
|
||||
<View className={styles.title}>{item.name}
|
||||
<Text className={styles.fg}>(</Text>
|
||||
<Text className={styles.num}>{item.product_color_list?.length || 0}</Text>
|
||||
<Text className={styles.fg}>)</Text>
|
||||
</View>
|
||||
{/* is_top === 3 代表该收藏夹是默认收藏夹 */}
|
||||
{
|
||||
item.is_top !== 3 && <View onClick={e => handleEditCollection(e, item)}>
|
||||
<IconFont name="icon-bianji" size={36}></IconFont>
|
||||
</View>
|
||||
}
|
||||
</View>
|
||||
<View className={styles.class_prefix_bottom}>
|
||||
<Text>{item.remark}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<IconFont name="icon-shangla" size={36} customClassName={classnames(isOpen ? styles.iconfont_show : styles.iconfont_hide)}></IconFont>
|
||||
<IconFont name="icon-xiala" size={36} customClassName={classnames(!isOpen ? styles.iconfont_show : styles.iconfont_hide)}></IconFont>
|
||||
</View>
|
||||
<View className={styles.class_con} style={isOpen ? { maxHeight: `${10 * 260}rpx` } : { maxHeight: 0 }} >
|
||||
<View className={styles.products_list}>
|
||||
{item.product_color_list?.map((subItem: any) => {
|
||||
return <ProductItem checked={checkedMap?.[item.id]?.[subItem.product_id]} onCheckedChange={onCheckedChange} filterChecked={filterChecked} metaDataId={item.id} event={collectionEvents} item={subItem} key={subItem.product_id} openCheckBox={isManageStatus} />
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</LayoutBlock>
|
||||
}
|
||||
const CollectionItemWithMemo = memo(CollectionItem)
|
||||
/**
|
||||
* *******************
|
||||
* * 收藏夹页面本体 *
|
||||
* *******************
|
||||
*/
|
||||
const Collection = () => {
|
||||
useLogin()
|
||||
|
||||
// 获取搜索数据
|
||||
const [searchData, setSearchData] = useState('')
|
||||
// 是否首次进入
|
||||
const isFirst = useRef(true)
|
||||
const onSearch = useCallback((e) => {
|
||||
setSearchData(() => e)
|
||||
}, [])
|
||||
|
||||
// 获取列表
|
||||
const [list, setList] = useState([])
|
||||
const { fetchData: fetchDataList } = FavoriteListApi()
|
||||
const { fetchData: fetchDataList, state: favoriteState } = FavoriteListApi()
|
||||
const [favoriteData, setFavoriteData] = useState<{ list: any[]; total: number }>({ list: [], total: 0 })
|
||||
// 获取列表
|
||||
const getFavoriteList = async() => {
|
||||
const res = await fetchDataList(getFilterData({ name: searchData }))
|
||||
setList(() => res.data.list)
|
||||
setFavoriteData({ list: res.data.list, total: res.data.total })
|
||||
}
|
||||
const changeOpenCon = (item) => {
|
||||
item.openStatus = !item.openStatus
|
||||
setList(e => [...e])
|
||||
// 当前选中的收藏夹
|
||||
const [currentSelection, setCurrentSelection] = useState<number>(0)
|
||||
// 更新当前选中的收藏夹的id
|
||||
const updateCurrentSelection = (current) => {
|
||||
console.log('updateCurrentSelection current', current)
|
||||
setCurrentSelection(current)
|
||||
}
|
||||
useDidShow(() => {
|
||||
getFavoriteList()
|
||||
})
|
||||
// 创建收藏夹
|
||||
const [collectioinShow, setCollectioinShow] = useState(false)
|
||||
const closeCollection = useCallback(() => {
|
||||
setCollectioinShow(false)
|
||||
}, [])
|
||||
// ---------勾选逻辑---------
|
||||
const [checkedMap, setCheckedMap] = useState<CheckedMap>({})
|
||||
|
||||
// 更多编辑
|
||||
const [initData, setInitData] = useState({
|
||||
remark: '',
|
||||
name: '',
|
||||
id: 0,
|
||||
})
|
||||
const creatShow = () => {
|
||||
setCollectioinShow(true)
|
||||
setInitData(() => ({ remark: '', name: '', id: 0 }))
|
||||
}
|
||||
useEffect(() => {
|
||||
getFavoriteList()
|
||||
}, [searchData])
|
||||
// 新增
|
||||
const { fetchData } = CreateFavoriteApi()
|
||||
const onCreate = async(submitData) => {
|
||||
if (!submitData.name) { return alert.none('请输入收藏夹名称!') }
|
||||
const res = await fetchData({ ...submitData })
|
||||
if (res.success) {
|
||||
alert.success('创建成功')
|
||||
getFavoriteList()
|
||||
}
|
||||
else {
|
||||
alert.error('创建失败')
|
||||
}
|
||||
}
|
||||
|
||||
const selectInfo = useRef<any>(null)
|
||||
const [updateShow, setUpdateShow] = useState(false)
|
||||
const closeUpdate = useCallback(() => {
|
||||
setUpdateShow(false)
|
||||
}, [])
|
||||
const moreUpdate = (item, e) => {
|
||||
e.stopPropagation()
|
||||
selectInfo.current = item
|
||||
console.log('item:::', item)
|
||||
setInitData(e => ({ ...e, remark: item.remark, name: item.name, id: item.id }))
|
||||
setUpdateShow(true)
|
||||
}
|
||||
|
||||
// 删除改收藏夹
|
||||
const { fetchData: delFetchData } = DelFavoriteApi()
|
||||
const onDeleteCollect = useCallback(() => {
|
||||
if (!selectInfo.current.id) { return alert.error('参数不正确!') }
|
||||
if (selectInfo.current.id == 1) { return alert.none('删除失败,该文件夹不能删除!') }
|
||||
Taro.showModal({
|
||||
content: '确认删除该文件夹?',
|
||||
async success(res) {
|
||||
if (res.confirm) {
|
||||
const res = await delFetchData({ id: selectInfo.current.id })
|
||||
if (res.success) {
|
||||
alert.success('删除成功')
|
||||
getFavoriteList()
|
||||
}
|
||||
else {
|
||||
alert.error('删除失败')
|
||||
}
|
||||
}
|
||||
else if (res.cancel) {
|
||||
console.log('用户点击取消')
|
||||
}
|
||||
const onCheckedChange = (id: number, itemId: number, checked: boolean) => {
|
||||
console.log('onCheckedChange', itemId, checked)
|
||||
const newCheckedMap = Object.assign({}, checkedMap, {
|
||||
[id]: {
|
||||
...checkedMap[id],
|
||||
[itemId]: checked,
|
||||
},
|
||||
})
|
||||
closeUpdate()
|
||||
}, [])
|
||||
setCheckedMap(newCheckedMap)
|
||||
}
|
||||
// 过滤符合勾选条件的数据
|
||||
const filterChecked = (id: number, filter?: () => boolean) => {
|
||||
if (!id) { return }
|
||||
if (!checkedMap[id]) {
|
||||
checkedMap[id] = {}
|
||||
}
|
||||
console.log('filterChecked', checkedMap[id])
|
||||
const checkedSelections = Object.entries(checkedMap[id])
|
||||
// 通过这个filter 筛选出所有checked状态为true的项
|
||||
const filteredWithId = checkedSelections.filter(entries => Boolean(entries[1])).map(([checkedId]) => Number(checkedId))
|
||||
const currentCollectionItem = favoriteData.list.find(item => item.id === id)
|
||||
console.log(filteredWithId, currentCollectionItem)
|
||||
const filtered = currentCollectionItem.product_color_list?.filter(({ product_id }) => filteredWithId.includes(product_id)) || []
|
||||
return filter ? filtered.filter(filter) : filtered
|
||||
}
|
||||
// ---------勾选逻辑---------
|
||||
useDidShow(() => {
|
||||
getFavoriteList()
|
||||
isFirst.current = false
|
||||
})
|
||||
|
||||
// 编辑
|
||||
const { fetchData: updateFavoriteFetchData } = UpdateFavoriteApi()
|
||||
const onUpdateShow = useCallback(() => {
|
||||
setCollectioinShow(true)
|
||||
}, [])
|
||||
const onUpdate = async(submitData) => {
|
||||
if (!submitData.name) { return alert.none('请输入收藏夹名称!') }
|
||||
const res = await updateFavoriteFetchData({ ...submitData })
|
||||
if (res.success) {
|
||||
alert.success('编辑成功')
|
||||
useEffect(() => {
|
||||
if (!isFirst.current) {
|
||||
getFavoriteList()
|
||||
closeUpdate()
|
||||
}
|
||||
}, [searchData, isFirst.current])
|
||||
|
||||
const contentHeightWithBottomBar = useRef<string>('auto')
|
||||
const [contentStyleObject, setContentStyleObject] = useState<React.CSSProperties>({ height: 'auto' })
|
||||
// 获取显示底部全选栏时 content的高度
|
||||
const handleLayout = () => {
|
||||
const query = Taro.createSelectorQuery()
|
||||
query.select('#bottomBar').boundingClientRect()
|
||||
query.select('#scrollContent').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
console.log('res', res)
|
||||
const bottomBarHeight = res[0].height
|
||||
const contentHeight = res[1].height
|
||||
contentHeightWithBottomBar.current = `${contentHeight - bottomBarHeight}px`
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
handleLayout()
|
||||
}, [])
|
||||
|
||||
// 消息机制
|
||||
useEffect(() => {
|
||||
collectionEvents.on('updateCurrentSelection', updateCurrentSelection)
|
||||
return () => {
|
||||
collectionEvents.off('updateCurrentSelection', updateCurrentSelection)
|
||||
}
|
||||
})
|
||||
|
||||
const multipleSelection = useMemo(() => {
|
||||
const selections = filterChecked(currentSelection)
|
||||
console.log('selections', selections)
|
||||
if (selections && selections.length !== 0) {
|
||||
return selections.map(item => item.product_id)
|
||||
}
|
||||
else {
|
||||
alert.error('编辑失败')
|
||||
return []
|
||||
}
|
||||
}, [checkedMap, filterChecked])
|
||||
|
||||
// 取消收藏
|
||||
const { fetchData: delFavoriteProductFetchData } = DelFavoriteProductApi()
|
||||
const onDelCollection = async() => {
|
||||
if (multipleSelection.length == 0) { return alert.none('请选择要取消面料') }
|
||||
const showModalRes = await Taro.showModal({
|
||||
title: '是否要取消收藏',
|
||||
confirmText: '是',
|
||||
cancelText: '否',
|
||||
})
|
||||
if (showModalRes.confirm) {
|
||||
const res = await delFavoriteProductFetchData({ favorite_id: currentSelection, product_id: multipleSelection })
|
||||
if (res.success) {
|
||||
getFavoriteList()
|
||||
alert.none('已取消收藏')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onBatchManagement = useCallback(() => {
|
||||
goLink('/pages/collection/collectionClass/index', { id: initData.id })
|
||||
closeUpdate()
|
||||
}, [initData])
|
||||
|
||||
// 操作文件夹
|
||||
const onCreatSuccess = (submitData) => {
|
||||
if (!initData.id) {
|
||||
onCreate(submitData)
|
||||
}
|
||||
else {
|
||||
onUpdate({ ...submitData, id: initData.id })
|
||||
}
|
||||
setCollectioinShow(false)
|
||||
const [isManageStatus, setManageStatus] = useState(false)
|
||||
// const [isSelectAll, setSelectAll] = useState(false)
|
||||
// 全选
|
||||
const isSelectAll = useMemo(() => {
|
||||
const product_color_list = favoriteData.list.find(item => item.id === currentSelection)?.product_color_list || []
|
||||
return product_color_list.length !== 0 && filterChecked(currentSelection).length === product_color_list.length
|
||||
}, [currentSelection, favoriteData.list, filterChecked])
|
||||
// 全选和反选的函数
|
||||
const onCheckedAllChange = (checkedAll: boolean) => {
|
||||
const product_color_list = favoriteData.list.find(item => item.id === currentSelection).product_color_list
|
||||
const newCheckedMap: CheckedMap = JSON.parse(JSON.stringify((checkedMap)))
|
||||
product_color_list.forEach((item) => {
|
||||
newCheckedMap[currentSelection][item.product_id] = checkedAll
|
||||
})
|
||||
console.log('newCheckedMap==+>', newCheckedMap)
|
||||
setCheckedMap(newCheckedMap)
|
||||
}
|
||||
// 点击管理
|
||||
const onStartToManage = () => {
|
||||
setManageStatus((isManageStatus) => {
|
||||
// 控制动画效果
|
||||
if (isManageStatus) {
|
||||
setContentStyleObject({ height: 'auto', flex: '1 1 auto' })
|
||||
}
|
||||
else {
|
||||
setContentStyleObject({
|
||||
flex: 'unset',
|
||||
height: `${contentHeightWithBottomBar.current}`,
|
||||
})
|
||||
}
|
||||
return !isManageStatus
|
||||
})
|
||||
}
|
||||
|
||||
// 新建收藏夹
|
||||
const handleAddNewCollection = () => {
|
||||
goLink('/pages/collection/collectionDetail/index', { title: '新建收藏夹', isEdit: false, editData: null })
|
||||
}
|
||||
|
||||
const [showMovePopup, setShowMovePopup] = useState(false)
|
||||
const closeMovePopup = useCallback(() => {
|
||||
setShowMovePopup(false)
|
||||
}, [])
|
||||
// 移动到
|
||||
const handleMultipleMove = () => {
|
||||
setShowMovePopup(true)
|
||||
}
|
||||
// 删除
|
||||
const handleMultipleDelete = () => {
|
||||
onDelCollection()
|
||||
}
|
||||
// 数据加载状态
|
||||
const statusMore = useMemo(() => {
|
||||
return dataLoadingStatus({ list: favoriteData.list, total: favoriteData.total, status: favoriteState.loading })
|
||||
}, [favoriteState, favoriteData])
|
||||
return (
|
||||
<View className={styles.collection_main}>
|
||||
<View className={styles.search}>
|
||||
<Search style={{ width: '100%' }} debounceTime={300} changeOnSearch={onSearch} placeholder="请输入面料关键词" />
|
||||
<View className={styles.miconfont_con} onClick={creatShow}><Text className={classnames(styles.miconfont, 'iconfont icon-jia')}></Text></View>
|
||||
</View>
|
||||
<View className={styles.class_list}>
|
||||
{list?.map((item: any, key) => <View className={styles.class_item} key={key}>
|
||||
<View key={item.id} className={styles.class_title} onClick={() => changeOpenCon(item)}>
|
||||
<Text className={classnames(styles.miconfont_left, 'iconfont icon-a-moreback', item.openStatus ? styles.miconfont_open : styles.miconfont_close)}></Text>
|
||||
<View className={styles.title}>{item.name}
|
||||
{item.product_color_list && <><Text className={styles.fg}>·</Text><Text className={styles.num}>{item.product_color_list.length}</Text></>}
|
||||
<View className={styles.collection_content} >
|
||||
|
||||
<View className={styles.search}>
|
||||
<Search showBtn={false} changeOnSearch={onSearch} placeholder="请输入面料关键词" >
|
||||
<View className={styles.flexBox} onClick={onStartToManage}>
|
||||
{isManageStatus
|
||||
? (
|
||||
<IconText svg iconName="icon-guanli" text="退出" color="#4581ff" customClass={styles['icon--manage--cancel']} />
|
||||
)
|
||||
: (
|
||||
<IconText svg iconName="icon-guanli" text="管理" />
|
||||
)}
|
||||
</View>
|
||||
<View className={styles.more} onClick={e => moreUpdate(item, e)}>更多</View>
|
||||
</Search>
|
||||
</View>
|
||||
<LayoutBlock circle customClassName={styles.layout} onClick={handleAddNewCollection}>
|
||||
<View className={styles.layoutBlock}>
|
||||
<IconFont customClassName={styles.icon} name="icon-shoucangjia" size={60} ></IconFont>
|
||||
<Text className={styles.content}>点击新建收藏夹</Text>
|
||||
</View>
|
||||
<View className={styles.class_con} style={item.openStatus ? { maxHeight: `${10 * 260}rpx` } : { maxHeight: 0 }} >
|
||||
<Product productList={item.product_color_list || []} />
|
||||
</View>
|
||||
</View>)}
|
||||
</LayoutBlock>
|
||||
<View className={styles.scrollContent} id="scrollContent" style={contentStyleObject}>
|
||||
<InfiniteScroll
|
||||
statusMore={statusMore}
|
||||
>
|
||||
{favoriteData.list?.map((item: any, key) =>
|
||||
(
|
||||
<CollectionItemWithMemo checkedMap={checkedMap} onCheckedChange={onCheckedChange} filterChecked={filterChecked} selectId={currentSelection} key={key} item={item} isManageStatus={isManageStatus} />
|
||||
),
|
||||
)}
|
||||
</InfiniteScroll>
|
||||
</View>
|
||||
</View>
|
||||
<UpdatePopup show={updateShow} onClose={closeUpdate} onDelete={onDeleteCollect} onUpdate={onUpdateShow} onBatchManagement={onBatchManagement} />
|
||||
<CreatePopup defaultValue={initData} show={collectioinShow} onClose={closeCollection} onSuccess={onCreatSuccess} />
|
||||
<View className={classnames(styles.bottomBar, isManageStatus ? styles.showBottomBar : '')} id="bottomBar">
|
||||
<View className={styles.bottomLeft}>
|
||||
<MCheckbox
|
||||
status={isSelectAll}
|
||||
round
|
||||
size="small"
|
||||
onSelect={() => onCheckedAllChange(true)}
|
||||
onClose={() => onCheckedAllChange(false)}
|
||||
customClassName={styles.multipleCheckbox}
|
||||
customTextClass={styles.multipleCheckbox__text}
|
||||
>
|
||||
全选
|
||||
</MCheckbox>
|
||||
</View>
|
||||
<View className={styles.bottomRight}>
|
||||
<NormalButton type="danger" plain round size="normal" onClick={handleMultipleMove} customStyles={{ padding: '0 50rpx', margin: '0 40rpx' }}>
|
||||
<Text style={{ fontSize: '30rpx' }}>移动到</Text>
|
||||
</NormalButton>
|
||||
<NormalButton type="danger" round size="normal" onClick={handleMultipleDelete} customStyles={{ padding: '0 60rpx' }}>
|
||||
<Text style={{ fontSize: '30rpx' }}>删除</Text>
|
||||
</NormalButton>
|
||||
</View>
|
||||
</View>
|
||||
<MoveCollectionPopup onSuccess={getFavoriteList} collectionList={favoriteData.list} show={showMovePopup} onClose={closeMovePopup} ids={multipleSelection} sourceId={currentSelection} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default Collection
|
||||
|
||||
@ -130,7 +130,7 @@ const Details = (props: Params) => {
|
||||
async(val) => {
|
||||
const res = await addFavoritefetchData({ favorite_id: val.id, product_id: Number(params.id) })
|
||||
if (res.success) {
|
||||
alert.success('添加成功')
|
||||
alert.none('收藏成功')
|
||||
setCollectStatus(true)
|
||||
getProductDetail()
|
||||
}
|
||||
|
||||
@ -1,33 +1,42 @@
|
||||
|
||||
$color_bg_one: #F8F8F8;
|
||||
$color_font_one: #3C3C3C;
|
||||
$color_font_two: #ABABAB;
|
||||
$color_bg_one: #f8f8f8;
|
||||
$color_font_one: #3c3c3c;
|
||||
$color_font_two: #ababab;
|
||||
$color_font_three: #707070;
|
||||
$color_main: #007AFF;
|
||||
$color_main: #007aff;
|
||||
|
||||
$font_size_big: 32px;
|
||||
$font_size: 28px;
|
||||
$font_size_medium: 24px;
|
||||
$font_size_min: 22px;
|
||||
|
||||
$color_main: #4581ff;
|
||||
$color_danger: #e64340;
|
||||
$color_warning: #e6a23c;
|
||||
$color_money: #f64861;
|
||||
$color_info: #909090;
|
||||
|
||||
$color_bulk: #0d7cff; // 大货
|
||||
$color_plate: #f79b31; // 剪板
|
||||
$color_bulkCut: #0ac76f; // 散剪
|
||||
|
||||
$borderStyle: solid;
|
||||
$borderColor: #ebebeb;
|
||||
$opacity-disabled: 0.3;
|
||||
|
||||
//安全底部距离
|
||||
.common_safe_area_y {
|
||||
width: 100%;
|
||||
height: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
|
||||
height: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
|
||||
width: 100%;
|
||||
height: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
|
||||
height: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
|
||||
}
|
||||
|
||||
//省略号
|
||||
@mixin common_ellipsis($params:1) {
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
white-space:normal;
|
||||
text-overflow:ellipsis;
|
||||
word-break:break-all;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: $params;
|
||||
|
||||
|
||||
@mixin common_ellipsis($params: 1) {
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
white-space: normal;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: $params;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import Taro from '@tarojs/taro'
|
||||
import dayjs from 'dayjs'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import type { SetStateAction } from 'react'
|
||||
import { SubscriptionMessageApi } from '@/api/user'
|
||||
|
||||
// 倒计时hook
|
||||
@ -91,3 +92,30 @@ export const UseSubscriptionMessage = () => {
|
||||
openSubscriptionMessage,
|
||||
}
|
||||
}
|
||||
|
||||
interface UsePropsValueOptions<T> {
|
||||
value?: T
|
||||
defaultValue: T
|
||||
onChange?: (v: T) => void
|
||||
}
|
||||
|
||||
export function usePropsValue<T>(options: UsePropsValueOptions<T>) {
|
||||
const { value, defaultValue, onChange } = options
|
||||
|
||||
const [, setForceUpdate] = useState({})
|
||||
|
||||
const stateRef = useRef<T>(value !== undefined ? value : defaultValue)
|
||||
if (value !== undefined) {
|
||||
stateRef.current = value
|
||||
}
|
||||
|
||||
const setState = useCallback((v: SetStateAction<T>, forceTrigger = false) => {
|
||||
// `forceTrigger` 意思是 触发 `onChange` 不管 `v` 是否和 `stateRef.current` 相等
|
||||
const nextValue = typeof v === 'function' ? (v as (prevState: T) => T)(stateRef.current) : v
|
||||
if (!forceTrigger && nextValue === stateRef.current) { return }
|
||||
stateRef.current = nextValue
|
||||
setForceUpdate({})
|
||||
return onChange?.(nextValue)
|
||||
}, [])
|
||||
return [stateRef.current, setState] as const
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user