对接完添加购物车

This commit is contained in:
czm 2022-05-09 18:52:08 +08:00
parent b5e967779c
commit f3c818f549
15 changed files with 212 additions and 79 deletions

View File

@ -10,3 +10,14 @@ export const GetShoppingCartApi = () => {
method: "get",
})
}
/**
*
* @returns
*/
export const AddShoppingCartApi = () => {
return useRequest({
url: `/v1/mall/shoppingCart/productColor/list`,
method: "post",
})
}

View File

@ -13,7 +13,7 @@ import { useRequest } from "@/use/useHttp"
/**
*
*/
export const GetSelfUserInfoApi = () => {
export const GetAdminUserInfoApi = () => {
return useRequest({
url: `/v1/mall/user/info`,
method: "get",

View File

@ -5,11 +5,11 @@
// export const BASE_URL = `http://192.168.0.89:40001/lymarket`
// export const BASE_URL = `http://192.168.1.165:40001/lymarket` // 王霞
// export const BASE_URL = `https://test.zzfzyc.com/lymarket` // 测试环境
// export const BASE_URL = `http://192.168.1.30:40001/lymarket` // 发
export const BASE_URL = `http://192.168.1.30:40001/lymarket` // 发
// 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.165:40001/lymarket` // 王霞
export const BASE_URL = `http://192.168.1.224:50001/lymarket` // 添
// export const BASE_URL = `http://192.168.1.224:50001/lymarket` // 添
// CDN
// 生成密钥

View File

@ -42,7 +42,7 @@ export const throttle = (fn, delay) => {
export const getFilterData = (val = {}, arr = []) => {
let res = {}
for(let key in val) {
if(val[key]!=undefined&&val[key]!=null&&val[key]!=''&&(!arr.includes(key))){
if(val[key]!==undefined&&val[key]!==null&&val[key]!==''&&(!arr.includes(key))){
if(val[key] instanceof Number){
if(!isNaN(val[key])) {
res[key] = val[key]

View File

@ -1,13 +1,13 @@
.checkbox_main{
width: 60px;
height: 60px;
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
.checkbox_item{
width: 40px;
height: 40px;
width: 30px;
height: 30px;
border: 1px solid #707070;
border-radius: 50%;
text-align: center;
@ -17,10 +17,10 @@
background-color: $color_main;
border: 0;
color: #fff;
width: 44px;
height: 44px;
width: 30px;
height: 30px;
text-align: center;
line-height: 44px;
line-height: 30px;
.miconfont{
font-size: 26px;
}

View File

@ -26,7 +26,7 @@ export default ({onSelect, onClose, status = false}: params) => {
<>
<View className={styles.checkbox_main} onClick={() => onSelectEven()}>
<View className={classnames(styles.checkbox_item, selected&&styles.checkbox_item_select)}>
{selected&&<View className={classnames('iconfont', 'icon-tick_gou', styles.miconfont)}></View>}
{selected&&<View className={classnames('iconfont', 'icon-tick', styles.miconfont)}></View>}
</View>
</View>
</>

View File

@ -59,7 +59,6 @@
.checkbox{
display: flex;
align-items: center;
}
.img{
width: 126px;
@ -80,6 +79,7 @@
.title{
font-size: $font_size;
color: $color_font_one;
@include common_ellipsis;
}
.subtitle{
color: $color_font_two;
@ -101,6 +101,7 @@
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-end;
.price{
font-size: $font_size;
font-weight: 700;

View File

@ -5,17 +5,24 @@ import MCheckbox from "@/components/checkbox";
import LoadingCard from "@/components/loadingCard";
import InfiniteScroll from "@/components/infiniteScroll";
import styles from "./index.module.scss"
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import Taro from "@tarojs/taro";
import { goLink } from "@/common/common";
import {GetShoppingCartApi} from "@/api/shopCart"
import { formatHashTag, formatMillionYuan } from "@/common/fotmat";
type param = {
show?: true|false,
onClose?: () => void
}
export default ({show = false, onClose}: param) => {
const selectList = ['不限', '剪板', '散剪', '大货']
const selectList = [
{title:'不限', unit:'', eunit:''},
{title:'大货', unit:'件', eunit:'kg'},
{title:'剪板', unit:'米', eunit:'m'},
{title:'散剪', unit:'米', eunit:'kg'},
]
const [selectIndex, setSelectIndex] = useState(0)
const selectProduct = (index:number) => {
setSelectIndex(index)
@ -28,7 +35,8 @@ export default ({show = false, onClose}: param) => {
const getShoppingCart = async () => {
setLoading(true)
const {data} = await fetchData()
setList(data)
console.log('color_list::', data)
setList(data.color_list)
setLoading(false)
}
@ -94,7 +102,16 @@ export default ({show = false, onClose}: param) => {
})
}
//格式化金额
const formatPirce = useCallback((price) => {
const {num} = formatMillionYuan(price, 100)
return Number(num)
}, [])
//格式化数量
const formatCount = useCallback((item) => {
return item.sale_mode == 0? item.roll + '件': item.length + 'm'
}, [])
return (
<View className={styles.shop_cart_main}>
@ -109,15 +126,15 @@ export default ({show = false, onClose}: param) => {
</View>
<View className={styles.search}>
{selectList.map((item, index) => {
return <View key={index} onClick={() => selectProduct(index)} className={classnames(styles.search_item, (selectIndex==index)&&styles.search_item_select)}>{item}</View>
return <View key={index} onClick={() => selectProduct(index)} className={classnames(styles.search_item, (selectIndex==index)&&styles.search_item_select)}>{item.title}</View>
})}
</View>
<View className={styles.con}>
{loading&&<LoadingCard/>}
{!loading&&list.length > 0&&<InfiniteScroll refresherTriggered={true} refresherEnabled={true} selfonScrollToLower={() => {console.log('触底了')}} paddingBottom={100}>
{!loading&&list?.length > 0&&<InfiniteScroll refresherTriggered={true} refresherEnabled={true} moreStatus={false} >
<View className={styles.product_list}>
{list.map((item, index) => {
{list?.map((item, index) => {
return <View key={index} className={styles.product_item}>
<View className={styles.checkbox}>
<MCheckbox status={item.select} onSelect={() => selectCallBack(item)} onClose={() => colseCallBack(item)}/>
@ -126,19 +143,19 @@ export default ({show = false, onClose}: param) => {
<Image src="https://bpic.588ku.com//back_origin_min_pic/22/01/11/aa3da17bab9a6556564028e4f1d77874.jpg!/fw/750/quality/99/unsharp/true/compress/true"/>
</View>
<View className={styles.des}>
<View className={styles.title}>{item.title}</View>
<View className={styles.subtitle}>07703# 21S单面平纹()</View>
<View className={styles.tag}></View>
<View className={styles.title}>{formatHashTag(item.product_code, item.product_name)}</View>
<View className={styles.subtitle}>{item.product_color_code +' ' + item.product_color_name}</View>
<View className={styles.tag}>{item.sale_mode_name}</View>
</View>
<View className={styles.count}>
<View className={styles.price}><text></text>40.5<text>/kg</text></View>
<View className={styles.long}>×12m</View>
<View className={styles.price}><text></text>{formatPirce(item.sale_price)}<text>/kg</text></View>
<View className={styles.long}>×{formatCount(item)}</View>
</View>
</View>
})}
</View>
</InfiniteScroll>}
{!loading&&list.length == 0 &&<View className={styles.empty}>
{!loading&&list?.length == 0 &&<View className={styles.empty}>
<View className={styles.title}></View>
<View className={styles.btn}></View>
</View>}

View File

@ -1,6 +1,8 @@
export const SET_USERINFO = 'setUserInfo'
export const SET_ADMINUSERINFO = 'setAdminUserInfo'
export const SET_TOKEN = 'setToken'
export const SET_SESSIONKEY = 'setSessionkey'
export const CLEAR_TOKEN = 'clearToken'
export const CLEAR_SESSIONKEY = 'clearSessionkey'
export const CLEAR_USERINFO = 'clearUserInfo'
export const CLEAR_ADMINUSERINFO = 'clearAdminUserInfo'

View File

@ -8,12 +8,16 @@ import Big from 'big.js'
import classnames from "classnames";
import styles from "./index.module.scss"
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useSelector } from "@/reducers/hooks"
import {GetColorList} from "@/api/materialColor"
import { useRouter } from "@tarojs/taro";
import {AddShoppingCartApi} from "@/api/shopCart"
import Taro, { useRouter } from "@tarojs/taro";
import UseLogin from "@/use/useLogin"
import { formatHashTag, formatMillionYuan } from "@/common/fotmat";
import { getFilterData } from "@/common/util";
type param = {
show?: true|false,
onClose?: () => void,
@ -21,6 +25,8 @@ type param = {
productId?: number
}
export default memo(({show = false, onClose, title = '', productId = 0}: param) => {
const {adminUserInfo} = useSelector(state => state.userInfo)
const selectList = [
{id: 0, step:1, digits:0, maxNum:100000, defaultNum:1, title:'大货', unit:'件', eunit:'kg'},
{id: 1, step:1, digits:2, maxNum:9.99, defaultNum:1, title:'剪板', unit:'米', eunit:'m'},
@ -28,32 +34,53 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param)
]
const [selectIndex, setSelectIndex] = useState(0)
const selectProduct = (index:number) => {
setSelectIndex(index)
console.log('number::',index)
setSelectIndex(() => index)
}
//获取面料颜色列表
const {fetchData:colorFetchData} = GetColorList()
const {fetchData:colorFetchData, state: colorState} = GetColorList()
const [list, setList] = useState<any[]>([])
const [loading, setLoading] = useState(false)
const condition = useRef({physical_warehouse:1, sale_mode:selectIndex, product_id:0, code_or_name:null})
const condition = useRef({physical_warehouse:adminUserInfo.physical_warehouse, sale_mode:selectIndex, product_id:0, code_or_name:null})
const getColorList = async () => {
setLoading(() => true)
console.log('数据:::',getFilterData(condition.current))
let {data} = await colorFetchData(getFilterData(condition.current))
setList([...data.list])
const list = initList(data.list)
setList([...list])
setLoading(() => false)
}
const [showPopup, setShowPopup] = useState(false)
useEffect(() => {
console.log('colorState::',colorState)
}, [colorState])
//显示获取
useEffect(() => {
if(show) {
setSelectIndex(0)
condition.current.code_or_name = null
setSearchShow(false)
condition.current.product_id = productId
getColorList()
}
setShowPopup(show)
}, [show])
//卸载清空
//初始化列表数据
const initList = useCallback((list) => {
const newList = list.map(item => {
item.count = 0
item.show = false
return item
})
return newList
}, [])
//卸载数据
useEffect(() => {
return () => {
setList([])
@ -64,22 +91,28 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param)
const closePopup = () => {
onClose?.()
setShowPopup(false)
setList([])
}
//计算总数量和总米/件数
const [selectCount, setSelectCount] = useState({
const [selectCount, setSelectCount] = useState<{sumCount:number, kindCount:number, color_list:any[]}>({
sumCount: 0,
kindCount: 0
kindCount: 0,
color_list: []
})
useEffect(() => {
let sumCount = 0, kindCount = 0
let sumCount = 0, kindCount = 0, color_list:any[] = []
let color_list_info = {}
list.map(item => {
if(item.count > 0) {
sumCount = Big(sumCount).add(item.count).toNumber()
kindCount ++
color_list_info = selectIndex == 0? {product_color_id:item.id, roll:item.count}:{product_color_id:item.id, length:item.count}
color_list.push(color_list_info)
}
})
setSelectCount({sumCount, kindCount})
setSelectCount({...selectCount, sumCount, kindCount, color_list})
}, [list])
//计数组件
@ -92,7 +125,6 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param)
const onAdd = (item) => {
item.show = true
item.count = selectList[selectIndex].defaultNum
console.log('aa:::',item.count)
setList((list) => [...list])
}
@ -104,8 +136,32 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param)
//添加购物车
const {getSelfUserInfo} = UseLogin()
const addShopCart = () => {
getSelfUserInfo()
const {fetchData:addFetchData} = AddShoppingCartApi()
const addShopCart = async () => {
if(selectCount.sumCount == 0) {
Taro.showToast({
icon:'none',
title:'请选择面料颜色!'
})
return false
}
await getSelfUserInfo()
const state = await addFetchData({
"sale_mode": selectIndex,
color_list: selectCount.color_list
})
if(state.success) {
Taro.showToast({
title:'添加成功'
})
onClose?.()
} else {
Taro.showToast({
icon:'none',
title: state.msg
})
}
}
//显示金额
@ -123,12 +179,10 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param)
//重置数据
useEffect(() => {
const newList = list.map(item => {
item.count = 0
item.show = false
return item
})
const newList = initList(list)
setList([...newList])
// condition.current.code_or_name = null
// setSearchShow(false)
}, [selectIndex])
//筛选数据
@ -165,12 +219,13 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param)
<View className={styles.text} onClick={() => clearSearch()}></View>
</View>}
<View className={styles.colorNum}>
<View className={styles.title}> (13) {list.length}</View>
<View className={styles.title}> (13)</View>
{!searchShow&&<View className={classnames('iconfont icon-sousuo', styles.miconfont)} onClick={() => changeSearchShow()}></View>}
</View>
<View className={styles.product_color_con}>
{list.length > 0&&<InfiniteScroll moreStatus={false}>
{(list.length <= 0 && colorState.loading)&&<LoadingCard/>}
{(list.length > 0&& !colorState.loading)&&<InfiniteScroll moreStatus={false}>
<View className={styles.color_con}>
{list.map(item => {
return <View className={styles.item}>
@ -199,8 +254,8 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param)
</View>
})}
</View>
</InfiniteScroll>||
<View className={styles.noData}></View>}
</InfiniteScroll>}
{(list.length <= 0 && !colorState.loading)&&<View className={styles.noData}></View>}
</View>
<View className={styles.buy_btn}>
<View className={styles.buy_btn_con}>

8
src/reducers/hooks.ts Normal file
View File

@ -0,0 +1,8 @@
//该方法纯粹只是个Ts类型定义文件
import { useSelector as useReduxSelector, TypedUseSelectorHook } from 'react-redux';
import { DataParam } from './userInfo';
type Params = {
userInfo: DataParam
}
export const useSelector: TypedUseSelectorHook<Params> = useReduxSelector;

View File

@ -2,11 +2,13 @@
import Taro from '@tarojs/taro'
import {
SET_USERINFO,
SET_ADMINUSERINFO,
SET_TOKEN,
SET_SESSIONKEY,
CLEAR_TOKEN,
CLEAR_USERINFO,
CLEAR_SESSIONKEY
CLEAR_SESSIONKEY,
CLEAR_ADMINUSERINFO,
} from '../constants/userInfo'
export type UserParam = {
@ -18,13 +20,28 @@ export type UserParam = {
province?: string,
gender?: number,
language?: string,
timestamp?: number
timestamp?: number,
physical_warehouse?: number,
physical_warehouse_name?: string,
}
export type UserAdminParam = {
avatar_url?: string,
open_id?: string,
physical_warehouse?: number,
physical_warehouse_name?: string,
union_id?: string,
user_code?: string,
user_id?: number,
user_name?: string,
wechat_user_open_id?: number
}
export type DataParam = {
token?: string
session_key?: string,
userInfo: UserParam
userInfo: UserParam,
adminUserInfo: UserAdminParam
}
type Action = {
@ -36,6 +53,7 @@ type Action = {
const INIT_USER = {
userInfo: Taro.getStorageSync('userInfo')?JSON.parse(Taro.getStorageSync('userInfo')):null,
adminUserInfo: Taro.getStorageSync('adminUserInfo')?JSON.parse(Taro.getStorageSync('adminUserInfo')):null,
token: Taro.getStorageSync('token')||'',
session_key: Taro.getStorageSync('session_key')||'',
}
@ -46,6 +64,9 @@ export default function counter (state = INIT_USER, action: Action) {
case SET_USERINFO:
Taro.setStorageSync('userInfo',JSON.stringify(data?.userInfo))
return {...state,...data}
case SET_ADMINUSERINFO:
Taro.setStorageSync('adminUserInfo',JSON.stringify(data?.adminUserInfo))
return {...state,...data}
case SET_TOKEN:
Taro.setStorageSync('token',data?.token)
return {...state,...data}
@ -61,6 +82,9 @@ export default function counter (state = INIT_USER, action: Action) {
case CLEAR_USERINFO:
Taro.removeStorageSync('userInfo')
return {...state, userInfo: null}
case CLEAR_ADMINUSERINFO:
Taro.removeStorageSync('adminUserInfo')
return {...state, adminUserInfo: null}
default:
return state
}

View File

@ -3,11 +3,11 @@ import { WX_APPID } from "@/common/constant"
import useUserInfo from "./useUserInfo"
import Taro, { useRouter } from "@tarojs/taro"
import { LoginApi } from "@/api/login"
import { GetWxUserInfoApi } from "@/api/user"
import { GetWxUserInfoApi, GetAdminUserInfoApi } from "@/api/user"
import qs from 'qs';
export default () => {
const {setToken, setSessionKey, setUserInfo, userInfo} = useUserInfo()
const {setToken, setSessionKey, setUserInfo, setAdminUserInfo, userInfo} = useUserInfo()
useEffect(() => {
console.log('userInfo::',userInfo.token)
@ -16,6 +16,7 @@ export default () => {
const router = useRouter()
//登录请求
const {fetchData} = LoginApi()
//微信登录
const wxLogin = () => {
return new Promise((reslove, reject) => {
@ -40,6 +41,9 @@ export default () => {
url: router.path +'?' + qs.stringify(params)
})
}
getAdminUserInfo()
//todo 删除本地授权用户信息,获取最新授权信息
} else {
Taro.showToast({
@ -62,6 +66,12 @@ export default () => {
}
//获取用户信息
const {fetchData: useFetchData} = GetAdminUserInfoApi()
const getAdminUserInfo = async () => {
let res = await useFetchData()
setAdminUserInfo(res.data)
}
//登录加checkLogin检查
const checkLogin = () => {

View File

@ -1,6 +1,6 @@
import { useDispatch, useSelector } from 'react-redux'
import { CLEAR_SESSIONKEY, SET_USERINFO, SET_TOKEN, SET_SESSIONKEY, CLEAR_USERINFO, CLEAR_TOKEN} from '@/constants/userInfo'
import {DataParam, UserParam} from '@/reducers/userInfo'
import { CLEAR_SESSIONKEY, SET_USERINFO, SET_TOKEN, SET_SESSIONKEY, CLEAR_USERINFO, CLEAR_TOKEN, SET_ADMINUSERINFO} from '@/constants/userInfo'
import {DataParam, UserParam, UserAdminParam} from '@/reducers/userInfo'
export default () => {
const userInfo = useSelector((state:DataParam) => state.userInfo) as DataParam
const dispatch = useDispatch()
@ -17,6 +17,10 @@ export default () => {
dispatch({type:SET_USERINFO, data:{userInfo}})
}
const setAdminUserInfo = (adminUserInfo: UserAdminParam) => {
dispatch({type:SET_ADMINUSERINFO, data:{adminUserInfo}})
}
const removeUserInfo = () => {
dispatch({type:CLEAR_USERINFO})
}
@ -32,6 +36,7 @@ export default () => {
return {
setToken,
setUserInfo,
setAdminUserInfo,
setSessionKey,
removeUserInfo,
removeToken,