From d0f069937b03611916618fa1e92f6f20941e4157 Mon Sep 17 00:00:00 2001 From: czm <2192718639@qq.com> Date: Tue, 10 May 2022 18:00:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E8=B4=AD=E7=89=A9=E8=BD=A6?= =?UTF-8?q?=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/shopCart.ts | 11 ++ src/common/constant.js | 4 +- src/common/fotmat.js | 11 ++ src/components/checkbox/index.module.scss | 18 ++- src/components/checkbox/index.tsx | 12 +- src/components/popup/index.tsx | 38 ++++-- src/components/shopCart/index.module.scss | 9 +- src/components/shopCart/index.tsx | 125 ++++++++++++++---- .../details/components/orderCount/index.tsx | 38 +++--- src/pages/details/components/swiper/index.tsx | 3 +- src/pages/details/index.module.scss | 8 +- src/pages/details/index.tsx | 58 +++++--- src/reducers/userInfo.ts | 2 + src/use/useLogin.ts | 78 +++++++---- 14 files changed, 296 insertions(+), 119 deletions(-) diff --git a/src/api/shopCart.ts b/src/api/shopCart.ts index 86368b8..87e0d32 100644 --- a/src/api/shopCart.ts +++ b/src/api/shopCart.ts @@ -20,4 +20,15 @@ export const AddShoppingCartApi = () => { url: `/v1/mall/shoppingCart/productColor/list`, method: "post", }) +} + +/** + * 批量删除购物车面料颜色 + * @returns +*/ +export const DelShoppingCartApi = () => { + return useRequest({ + url: `/v1/mall/shoppingCart/productColor`, + method: "delete", + }) } \ No newline at end of file diff --git a/src/common/constant.js b/src/common/constant.js index 21be554..7c65e86 100644 --- a/src/common/constant.js +++ b/src/common/constant.js @@ -9,7 +9,7 @@ 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:50002/lymarket` // 添 // CDN // 生成密钥 @@ -17,7 +17,7 @@ export const GET_UPLOAD_SIGN = `/upyun/getsign` // 请求签名 url export const UPLOAD_CDN_URL = `https://v0.api.upyun.com/` // 前缀 -export const IMG_CND_Prefix = "http://test.cdn.zzfzyc.com/" +export const IMG_CND_Prefix = "http://test.cdn.zzfzyc.com" // 上传图片视频 diff --git a/src/common/fotmat.js b/src/common/fotmat.js index 8bef05c..3cff723 100644 --- a/src/common/fotmat.js +++ b/src/common/fotmat.js @@ -1,3 +1,5 @@ +import { IMG_CND_Prefix } from "./constant"; + /** * 移除井号 * @param {String} val code 编码 @@ -133,3 +135,12 @@ export const toDecimal2 = (x) => { } return f; } + +/** + * 格式化图片路径 + * @param {*} url + * @returns + */ +export const formatImgUrl = (url) => { + return IMG_CND_Prefix + url +} \ No newline at end of file diff --git a/src/components/checkbox/index.module.scss b/src/components/checkbox/index.module.scss index fbd781e..345ad92 100644 --- a/src/components/checkbox/index.module.scss +++ b/src/components/checkbox/index.module.scss @@ -1,26 +1,30 @@ .checkbox_main{ - width: 40px; - height: 40px; + width: 50px; + height: 50px; display: flex; justify-content: center; align-items: center; } .checkbox_item{ - width: 30px; - height: 30px; + width: 40px; + height: 40px; border: 1px solid #707070; border-radius: 50%; text-align: center; line-height: 40px; } +.no_checkbox_item{ + border:0; + background-color: #DDDDDD; +} .checkbox_item_select{ background-color: $color_main; border: 0; color: #fff; - width: 30px; - height: 30px; + width: 40px; + height: 40px; text-align: center; - line-height: 30px; + line-height: 40px; .miconfont{ font-size: 26px; } diff --git a/src/components/checkbox/index.tsx b/src/components/checkbox/index.tsx index 31f1839..e79a1a4 100644 --- a/src/components/checkbox/index.tsx +++ b/src/components/checkbox/index.tsx @@ -4,13 +4,15 @@ import { useEffect, useState } from "react"; import styles from "./index.module.scss" type params = { - onSelect?: () => void, - onClose?: () => void, - status?: false|true + onSelect?: () => void, //选择触发 + onClose?: () => void, //取消触发 + status?: false|true //是否选中 + disabled?: false|true //是否禁用 } -export default ({onSelect, onClose, status = false}: params) => { +export default ({onSelect, onClose, status = false, disabled = false}: params) => { const [selected, SetSelected] = useState(false) const onSelectEven = () => { + if(disabled) return false let res = !selected if(res) { onSelect?.() @@ -25,7 +27,7 @@ export default ({onSelect, onClose, status = false}: params) => { return ( <> onSelectEven()}> - + {selected&&} diff --git a/src/components/popup/index.tsx b/src/components/popup/index.tsx index 43349cb..227f12e 100644 --- a/src/components/popup/index.tsx +++ b/src/components/popup/index.tsx @@ -1,18 +1,19 @@ import { View } from "@tarojs/components"; import style from "./index.module.scss" import classnames from "classnames"; -import { memo, ReactNode, useMemo } from "react"; +import { memo, ReactNode, useEffect, useMemo, useRef } from "react"; import CloseBtnIcon from "@/components/closeBtn" export interface Params { - title?: string, - show?: false|true, - showTitle?: false|true, - onClose?:() => void, - children?: ReactNode, - IconButton?: ReactNode, - showIconButton?: false|true, - position?: 'bottom'|'top'|'right' + title?: string, //标题 + show?: false|true, //显示显示弹窗 + showTitle?: false|true, //是否显示标题 + onClose?:() => void, //关闭事件 + children?: ReactNode, //插槽内容 + // IconButton?: ReactNode, // + showIconButton?: false|true, //是否显示关闭按钮 + position?: 'bottom'|'top'|'right', //弹出位置 + animationEnd?: () => void //弹出动画结束 } export default memo(( { @@ -22,9 +23,26 @@ export default memo(( onClose, showIconButton = false, children, - position = 'bottom' + position = 'bottom', + animationEnd }:Params) => { + const animationTime = useRef(null) + useEffect(() => { + if(show) { + animationTime.current = setTimeout(() => { + animationEnd?.() + }, 260) + } else { + clearTimeout(animationTime.current) + } + }, [show]) + + useEffect(() => { + return () => { + clearTimeout(animationTime.current) + } + }, []) return ( <> diff --git a/src/components/shopCart/index.module.scss b/src/components/shopCart/index.module.scss index 73c6cd7..ca891ed 100644 --- a/src/components/shopCart/index.module.scss +++ b/src/components/shopCart/index.module.scss @@ -41,7 +41,7 @@ } .con{ padding:30px; - padding-bottom: 0; + padding-bottom: 100px; box-sizing: border-box; flex:1; height: 0; @@ -54,7 +54,7 @@ display: flex; justify-content: space-between; &:nth-child(n+2) { - margin-top: 30px; + margin-top: 37px; } .checkbox{ display: flex; @@ -76,6 +76,8 @@ flex-direction: column; justify-content: space-between; margin-left: 20px; + padding-right: 10px; + box-sizing: border-box; .title{ font-size: $font_size; color: $color_font_one; @@ -97,6 +99,9 @@ } } } + .no_product_item_select{ + opacity: 0.3; + } .count{ display: flex; flex-direction: column; diff --git a/src/components/shopCart/index.tsx b/src/components/shopCart/index.tsx index ee199fa..16c6880 100644 --- a/src/components/shopCart/index.tsx +++ b/src/components/shopCart/index.tsx @@ -5,11 +5,11 @@ import MCheckbox from "@/components/checkbox"; import LoadingCard from "@/components/loadingCard"; import InfiniteScroll from "@/components/infiniteScroll"; import styles from "./index.module.scss" -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import Taro from "@tarojs/taro"; import { goLink } from "@/common/common"; -import {GetShoppingCartApi} from "@/api/shopCart" -import { formatHashTag, formatMillionYuan } from "@/common/fotmat"; +import {GetShoppingCartApi, DelShoppingCartApi} from "@/api/shopCart" +import { formatHashTag, formatImgUrl, formatMillionYuan } from "@/common/fotmat"; type param = { show?: true|false, @@ -17,17 +17,35 @@ type param = { } export default ({show = false, onClose}: param) => { const selectList = [ - {title:'不限', unit:'', eunit:''}, - {title:'大货', unit:'件', eunit:'kg'}, - {title:'剪板', unit:'米', eunit:'m'}, - {title:'散剪', unit:'米', eunit:'kg'}, + {value:-1, title:'不限', unit:'', eunit:''}, + {value:0, title:'大货', unit:'件', eunit:'kg'}, + {value:1,title:'剪板', unit:'米', eunit:'m'}, + {value:2,title:'散剪', unit:'米', eunit:'kg'}, + ] - const [selectIndex, setSelectIndex] = useState(0) + const [selectIndex, setSelectIndex] = useState(-1) const selectProduct = (index:number) => { setSelectIndex(index) } + useEffect(() => { + resetList() + setSelectStatus(true) + }, [selectIndex]) + + //重置勾选数据 + const resetList = () => { + list?.map(item => { + if(selectIndex == item.sale_mode || selectIndex == -1) { + item.select = true + } else { + item.select = false + } + }) + setList([...list]) + } + //获取数据 const [list, setList] = useState([]) const [loading, setLoading] = useState(false) @@ -35,15 +53,29 @@ export default ({show = false, onClose}: param) => { const getShoppingCart = async () => { setLoading(true) const {data} = await fetchData() - console.log('color_list::', data) - setList(data.color_list) + let color_list = data.color_list||[] + initList(color_list) + setList(color_list) setLoading(false) } + //初始化全部数据 + const initList = (color_list) => { + if(selectIndex == -1) { + color_list?.map(item => { + item.select = true + }) + } + } + //显示是展示数据 useEffect(() => { - if(!show) return - getShoppingCart() + if(!show) { + setList([]) + setSelectIndex(-1) + } else { + getShoppingCart() + } }, [show]) useEffect(() => { @@ -57,11 +89,12 @@ export default ({show = false, onClose}: param) => { setShowPopup(show) }, [show]) - + //全选反选 const [selectStatus, setSelectStatus] = useState(false) const selectAll = () => { list.map(item => { - item.select = !selectStatus + if(selectIndex == item.sale_mode || selectIndex == -1) + item.select = !selectStatus }) setSelectStatus(!selectStatus) setList([...list]) @@ -70,12 +103,29 @@ export default ({show = false, onClose}: param) => { //checkbox选中回调 const selectCallBack = (item) => { item.select = true + checkSelect() setList([...list]) } + //checkbox选中判断是否全部选中,全部选中后是全选,否则反选 + const checkSelect = () => { + let list_count = 0 + let select_count = 0 + list?.map(item => { + if(selectIndex == -1 || selectIndex == item.sale_mode) { + list_count ++ + if(item.select) select_count++ + } + }) + console.log('list_count::',list_count) + console.log('select_count::',select_count) + setSelectStatus(select_count == list_count) + } + //checkbox关闭回调 const colseCallBack = (item) => { item.select = false + checkSelect() setList([...list]) } @@ -85,16 +135,28 @@ export default ({show = false, onClose}: param) => { setShowPopup(false) } + //删除购物车内容 + const {fetchData:delShopFetchData} = DelShoppingCartApi() const delSelect = () => { Taro.showModal({ content: '删除所选商品?', - success: function (res) { + success: async function (res) { if (res.confirm) { - Taro.showToast({ - title: '成功', - icon: 'success', - duration: 2000 - }) + getSelectId() + const res = await delShopFetchData({id:selectIds.current}) + if(res.success) { + getShoppingCart() + Taro.showToast({ + title: '成功', + icon: 'success', + }) + } else { + Taro.showToast({ + title: res.msg, + icon: 'none', + }) + } + } else if (res.cancel) { console.log('用户点击取消') } @@ -102,6 +164,16 @@ export default ({show = false, onClose}: param) => { }) } + //获取面料选中的id + const selectIds = useRef([]) + const getSelectId = () => { + list?.map(item => { + if(selectIndex == -1 || selectIndex == item.sale_mode) { + item.select&&selectIds.current.push(item.id) + } + }) + } + //格式化金额 const formatPirce = useCallback((price) => { const {num} = formatMillionYuan(price, 100) @@ -115,7 +187,7 @@ export default ({show = false, onClose}: param) => { return ( - closePopup()}> + closePopup()} > {!selectStatus?'全选':'反选'} @@ -125,22 +197,21 @@ export default ({show = false, onClose}: param) => { - {selectList.map((item, index) => { - return selectProduct(index)} className={classnames(styles.search_item, (selectIndex==index)&&styles.search_item_select)}>{item.title} + {selectList.map((item) => { + return selectProduct(item.value)} className={classnames(styles.search_item, (selectIndex==item.value)&&styles.search_item_select)}>{item.title} })} - {loading&&} {!loading&&list?.length > 0&& {list?.map((item, index) => { - return + return - selectCallBack(item)} onClose={() => colseCallBack(item)}/> + selectCallBack(item)} onClose={() => colseCallBack(item)}/> - + {formatHashTag(item.product_code, item.product_name)} diff --git a/src/pages/details/components/orderCount/index.tsx b/src/pages/details/components/orderCount/index.tsx index 1efa7e7..4ac91dd 100644 --- a/src/pages/details/components/orderCount/index.tsx +++ b/src/pages/details/components/orderCount/index.tsx @@ -34,21 +34,25 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param) ] const [selectIndex, setSelectIndex] = useState(0) const selectProduct = (index:number) => { - console.log('number::',index) setSelectIndex(() => index) + //重置数据 + const newList = initList(list) + setList([...newList]) + condition.current.code_or_name = null + setSearchShow(false) } //获取面料颜色列表 const {fetchData:colorFetchData, state: colorState} = GetColorList() const [list, setList] = useState([]) const [loading, setLoading] = useState(false) - const condition = useRef({physical_warehouse:adminUserInfo.physical_warehouse, 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)) - const list = initList(data.list) - setList([...list]) + let lists = initList(data.list) + setList([...lists]) setLoading(() => false) } const [showPopup, setShowPopup] = useState(false) @@ -63,7 +67,6 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param) setSelectIndex(0) condition.current.code_or_name = null setSearchShow(false) - condition.current.product_id = productId getColorList() } @@ -138,6 +141,16 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param) const {getSelfUserInfo} = UseLogin() const {fetchData:addFetchData} = AddShoppingCartApi() const addShopCart = async () => { + try { + await getSelfUserInfo() + } catch(msg) { + Taro.showToast({ + icon:'none', + title:msg + }) + return false + } + if(selectCount.sumCount == 0) { Taro.showToast({ icon:'none', @@ -145,7 +158,6 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param) }) return false } - await getSelfUserInfo() const state = await addFetchData({ "sale_mode": selectIndex, color_list: selectCount.color_list @@ -165,7 +177,7 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param) } //显示金额 - const priceFormat = useCallback((item) => { + const priceFormat = (item) => { let price = 0 if(selectIndex == 0) { price = formatMillionYuan(item.bulk_price, 100).num @@ -175,15 +187,7 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param) price = formatMillionYuan(item.weight_cut_price, 100).num } return ¥{Number(price) }{' /' + selectList[selectIndex].eunit} - }, [list, selectIndex]) - - //重置数据 - useEffect(() => { - const newList = initList(list) - setList([...newList]) - // condition.current.code_or_name = null - // setSearchShow(false) - }, [selectIndex]) + } //筛选数据 const searchInput = (e) => { @@ -219,7 +223,7 @@ export default memo(({show = false, onClose, title = '', productId = 0}: param) clearSearch()}>取消 } - 颜色分类 (13) + 颜色分类 ({list.length}) {!searchShow&& changeSearchShow()}>} diff --git a/src/pages/details/components/swiper/index.tsx b/src/pages/details/components/swiper/index.tsx index d937f8d..7fa0497 100644 --- a/src/pages/details/components/swiper/index.tsx +++ b/src/pages/details/components/swiper/index.tsx @@ -1,3 +1,4 @@ +import { formatImgUrl } from "@/common/fotmat" import { Image, Swiper, SwiperItem, View } from "@tarojs/components" import { useMemo, useRef, useState } from "react" import styles from './index.module.scss' @@ -27,7 +28,7 @@ export default ({list = []}: params) => { {list.map((item) => { return - + })} diff --git a/src/pages/details/index.module.scss b/src/pages/details/index.module.scss index 2ac32b4..750aefa 100644 --- a/src/pages/details/index.module.scss +++ b/src/pages/details/index.module.scss @@ -145,7 +145,13 @@ background-color: $color_main; font-size: $font_size; color: #fff; - + position: relative; + .phoneBtn{ + background-color: rgba(0, 0, 0, 0); + position: absolute; + width: 100%; + height: 100%; + } } } } \ No newline at end of file diff --git a/src/pages/details/index.tsx b/src/pages/details/index.tsx index b2210cb..d663095 100644 --- a/src/pages/details/index.tsx +++ b/src/pages/details/index.tsx @@ -1,6 +1,6 @@ import { Button, Image, RichText, ScrollView, Swiper, SwiperItem, Text, View } from '@tarojs/components' -import Taro, { useDidShow, useRouter, useShareAppMessage } from '@tarojs/taro'; +import Taro, { useDidShow, usePullDownRefresh, useRouter, useShareAppMessage } from '@tarojs/taro'; import classnames from "classnames"; import DesSwiper from './components/swiper'; import OrderCount from './components/orderCount'; @@ -23,7 +23,8 @@ type params = { style?: Object } export default (props:params) => { - const {checkLogin} = useLogin() + const {checkLogin, getPhoneNumber, userInfo} = useLogin() + useDidShow(() => { checkLogin() }) @@ -39,6 +40,7 @@ export default (props:params) => { const getProductDetail = async () => { let {data} = await fetchData({id: router.params.id}) setProductInfo(data) + Taro.stopPullDownRefresh() } //面料名称 @@ -46,27 +48,11 @@ export default (props:params) => { return formatHashTag(productInfo.code, productInfo.name) },[productInfo]) - const list = [ - { - title:'数据', - img:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F811%2F021315104H2%2F150213104H2-3-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1651817947&t=5467a207f845ddfc7737d55934e6b26d', - url:'', - id:1 - }, - { - title:'数据', - img:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F811%2F021315104H2%2F150213104H2-3-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1651817947&t=5467a207f845ddfc7737d55934e6b26d', - url:'', - id:2 - } - ] - const [showCart, setShowCart] = useState(false) const [showOrderCount, setShowOrderCount] = useState(false) - const html = `

这里是详情

-
你好啊啊
+ const html = ` ` @@ -99,14 +85,36 @@ export default (props:params) => { return { title: '自定义转发标题', path: '/pages/details/index?id=10', - imageUrl: list[0].img + imageUrl: '' } }) + //开始下单 + const placeOrder = async (e:any) => { + try { + await getPhoneNumber(e.detail.code) + } catch(msg) { + Taro.showToast({ + icon:"none", + title: msg + }) + return false + } + setShowOrderCount(true) + } + + + //页面下拉刷新 + usePullDownRefresh(() => { + getProductDetail() + + }) + + return ( - + {productName} @@ -154,7 +162,13 @@ export default (props:params) => { 购物车 - setShowOrderCount(true)}>开始下单 + { + !userInfo.adminUserInfo?.is_authorize_phone&& + + 开始下单 + + || placeOrder(e)}>开始下单 + } setShowOrderCount(false)} title={productName} productId={productInfo.id}/> setShowCart(false)}/> diff --git a/src/reducers/userInfo.ts b/src/reducers/userInfo.ts index 5fe0ff5..5fbd4db 100644 --- a/src/reducers/userInfo.ts +++ b/src/reducers/userInfo.ts @@ -35,6 +35,8 @@ export type UserAdminParam = { user_id?: number, user_name?: string, wechat_user_open_id?: number + is_authorize_name?: false|true, + is_authorize_phone?: false|true } export type DataParam = { diff --git a/src/use/useLogin.ts b/src/use/useLogin.ts index 73377c0..c449363 100644 --- a/src/use/useLogin.ts +++ b/src/use/useLogin.ts @@ -3,7 +3,7 @@ import { WX_APPID } from "@/common/constant" import useUserInfo from "./useUserInfo" import Taro, { useRouter } from "@tarojs/taro" import { LoginApi } from "@/api/login" -import { GetWxUserInfoApi, GetAdminUserInfoApi } from "@/api/user" +import { GetWxUserInfoApi, GetAdminUserInfoApi, GetPhoneNumberApi } from "@/api/user" import qs from 'qs'; export default () => { @@ -99,38 +99,66 @@ export default () => { const {fetchData: fetchDataUserInfo} = GetWxUserInfoApi() const getSelfUserInfo = async () => { return new Promise((reslove, reject) => { - if(!userInfo.userInfo) { - Taro.getUserProfile({ - desc: '用于完善会员资料', - success: async (res) => { - if(!userInfo.session_key) { - await wxLogin() - } - const {data} = await fetchDataUserInfo({ - session_key: userInfo.session_key, - raw_data: res.rawData, - signature: res.signature, - encrypted_data: res.encryptedData, - iv: res.iv - }) - setUserInfo({...data}) - reslove(data) - }, - fail:(e) => { - reject(e) - } - }) - } else { - reslove(true) + if(userInfo.adminUserInfo.is_authorize_name) { + reslove(true) + return true } + Taro.getUserProfile({ + desc: '用于完善会员资料', + success: async (res) => { + if(!userInfo.session_key) { + await wxLogin() + } + const user_res = await fetchDataUserInfo({ + session_key: userInfo.session_key, + raw_data: res.rawData, + signature: res.signature, + encrypted_data: res.encryptedData, + iv: res.iv + }) + if(user_res.success) { + setUserInfo({...user_res.data}) + reslove(user_res.data) + getAdminUserInfo() + } else { + reject(user_res.msg) + } + + }, + fail:(e) => { + reject(e) + } + }) }) } + //获取手机号码 + const {fetchData: fetchDataUserPhone} = GetPhoneNumberApi() + const getPhoneNumber = (code) =>{ + return new Promise( async (reslove, reject) => { + if(userInfo.adminUserInfo.is_authorize_phone) { + reslove(true) + return true + } + const res = await fetchDataUserPhone({code}) + if(res.success) { + setUserInfo({...userInfo.userInfo, phone:res.data.phone_number}) + getAdminUserInfo() + reslove(res.data) + } else { + reject(res.msg) + } + + }) + } + return { checkLogin, wxLogin, - getSelfUserInfo + getSelfUserInfo, + getPhoneNumber, + userInfo } }