fix: 组合商品无法加购

This commit is contained in:
lukaijie
2022-03-17 15:24:46 +08:00
parent 843cda0fc0
commit c04aadfaf7
13 changed files with 664 additions and 86 deletions

View File

@@ -235,7 +235,6 @@ function SpSkuSelect(props) {
btnTxt = BUY_TOOL_BTNS[key].title
}
})
if (type == 'picker') {
return (
<AtButton circle type='primary' onClick={onClose}>

View File

@@ -93,6 +93,33 @@ export const BUY_TOOL_BTNS = {
NO_STORE: { title: '无货', key: 'nostore', btnStatus: 'disabled' }
}
export const COUPON_TYPE = {
gift: {
tag: '兑换券',
bg: 'linear-gradient(122deg, #F4C486 0%, #D4A570 100%)',
fc: '#AC8050',
invalidBg: 'linear-gradient(122deg, #D8D8D8 0%, #A9A9A9 100%)',
invalidFc: '#888888',
opacity: '0.4'
},
cash: {
tag: '满减券',
bg: 'linear-gradient(299deg, #679BDD 0%, #9AC5FF 100%)',
fc: '#4979B7',
invalidBg: 'linear-gradient(122deg, #D8D8D8 0%, #A9A9A9 100%)',
invalidFc: '#888888',
opacity: '0.4'
},
discount: {
tag: '折扣券',
bg: 'linear-gradient(126deg, #CCC0EF 0%, #7E6FA9 100%)',
fc: '#64578D',
invalidBg: 'linear-gradient(122deg, #D8D8D8 0%, #A9A9A9 100%)',
invalidFc: '#888888',
opacity: '0.4'
}
}
export const PAYTYPE = {
/** h5环境下 */
WXH5: 'wxpayh5',

View File

@@ -1,3 +1,5 @@
import { formatTime } from '@/utils'
export const COUPON_LIST = {
item_id: 'item_id',
item_name: 'item_name',
@@ -11,3 +13,21 @@ export const COUPON_LIST = {
item_spec_desc: 'item_spec_desc',
desc: 'desc'
}
export const COUPON_ITEM = {
title: 'title',
cardId: 'card_id',
cardType: 'card_type',
beginDate: ({ begin_date }) => formatTime(begin_date * 1000, 'YYYY.MM.DD'),
endDate: ({ end_date }) => formatTime(end_date * 1000, 'YYYY.MM.DD'),
tagClass: 'tagClass',
reduceCost: ({ reduce_cost }) => reduce_cost / 100,
leastCost: ({ least_cost }) => least_cost / 100,
discount: ({ discount }) => {
return (100 - discount) / 10
},
useBound: 'use_bound',
description: 'description',
quantity: ({ quantity }) => parseInt(quantity),
getNum: 'get_num'
}

View File

@@ -1,11 +1,147 @@
import React, { useEffect } from 'react'
import { useSelector } from 'react-redux'
import Taro from '@tarojs/taro'
import { View } from '@tarojs/components'
import { View, Text, Button } from '@tarojs/components'
import { useImmer } from 'use-immer'
import { SpImage } from '@/components'
import { classNames, styleNames } from '@/utils'
import { COUPON_TYPE } from '@/consts'
import './index.scss'
const initialState = {
isExpanded: false
}
function BaCoupon(props) {
return <View className='ba-coupon'></View>
const { info } = props
const [state, setState] = useImmer(initialState)
const { isExpanded } = state
if (!info) {
return null
}
const {
title,
cardId,
cardType,
beginDate,
endDate,
tagClass,
reduceCost,
leastCost,
discount,
useBound,
description,
quantity,
getNum
} = info
const { tag, invalidBg, bg } = COUPON_TYPE[cardType]
const couponTagBg = info.tagClass === 'used' || info.tagClass === 'overdue' ? invalidBg : bg
const getCouponValue = () => {
if (cardType === 'cash') {
return (
<View className='coupon-cash'>
<View className='coupon-value'>
<Text className='symbol'>¥</Text>
<Text className='value'>{reduceCost}</Text>
</View>
<View className='coupon-rule'>{`${leastCost}可用`}</View>
</View>
)
} else if (cardType === 'discount') {
return (
<View className='coupon-discount'>
<View className='coupon-value'>
<Text className='value'>{discount}</Text>
<Text className='symbol'></Text>
</View>
<View className='coupon-rule'>{`${leastCost}可用`}</View>
</View>
)
}
}
const content = description.split('\n') || []
return (
<View className='ba-coupon'>
<View className='ba-coupon-content'>
<View
className='ba-coupon-hd'
// style={styleNames({
// backgroundImage: `url(${process.env.APP_IMAGE_CDN}${'/coupon_FFF.png'})`
// })}
>
<View className='couponn-info'>
<View
className='coupon-tag'
style={styleNames({
background: couponTagBg
})}
>
{COUPON_TYPE[cardType].tag}
</View>
<Text className='title'>{title}</Text>
</View>
<View className='coupon-datetime'>{`有效期: ${beginDate} - ${endDate}`}</View>
<View className='coupon-desc'>
<Text className='coupon-desc-txt'>详细信息</Text>
<SpImage
src={`${isExpanded ? 'coupon_arrow_up.png' : 'coupon_arrow_down.png'}`}
width={24}
height={24}
onClick={() => {
setState((draft) => {
draft.isExpanded = !isExpanded
})
}}
/>
</View>
</View>
<View
className='ba-coupon-ft'
style={styleNames({
background: couponTagBg
})}
>
{getCouponValue()}
<View className='coupon-btn'>
{quantity > 0 && (
<View >
<Button
plain
openType='share'
data-info={cardId}
className={classNames('share-btn', {
disabled: quantity - getNum <= 0
})}
disabled={quantity - getNum <= 0}
>
分享给顾客
</Button>
</View>
)}
</View>
</View>
</View>
{isExpanded && (
<View className='ba-coupon-desc'>
{content.map((item, index) => (
<View className='desc-txt' key={index}>
{item}
</View>
))}
{useBound == '0' && <View className='desc-txt'>此优惠券适合全部商品使用</View>}
{useBound == '1' && <View className='desc-txt'>此优惠券仅适合指定商品使用</View>}
{(useBound == '2' || useBound == '3') && (
<View className='desc-txt'>此优惠券仅适合指定分类商品使用</View>
)}
{useBound == '4' && <View className='desc-txt'>此优惠券仅适合指定品牌商品使用</View>}
</View>
)}
</View>
)
}
BaCoupon.options = {

View File

@@ -0,0 +1,134 @@
.ba-coupon {
&-content {
display: flex;
height: 200px;
background: #ffffff;
// box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.1);
border-radius: 8px;
overflow: hidden;
position: relative;
&::before {
content: '';
width: 30px;
height: 30px;
background: #f5f5f5;
position: absolute;
left: 495px;
top: -15px;
border-radius: 15px;
}
&::after {
content: '';
width: 30px;
height: 30px;
background: #f5f5f5;
position: absolute;
left: 495px;
bottom: -15px;
border-radius: 15px;
}
}
&-hd {
flex: 1;
background-size: 100% 100%;
.coupon-tag {
display: inline-block;
padding: 0 6px;
border-radius: 8px;
font-size: 24px;
font-weight: 400;
color: #ffffff;
margin-right: 6px;
text-align: center;
}
.couponn-info {
margin: 28px 0 0 25px;
display: flex;
align-items: center;
}
.coupon-datetime {
font-size: 22px;
color: #555;
margin: 50px 0 0 25px;
}
.coupon-desc {
font-size: 22px;
color: #999;
margin: 8px 0 0 25px;
display: flex;
align-items: center;
.coupon-desc-txt {
margin-right: 6px;
}
}
}
&-ft {
width: 200px;
height: 200px;
.coupon-btn {
width: 140px;
height: 44px;
background: #ffffff;
box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.1);
border-radius: 45px;
margin: 18px auto;
}
.share-btn {
height: auto;
background: transparent;
line-height: 44px;
font-size: 24rpx;
padding: 0;
height: 44px;
border-width: 0;
color: #333;
}
.coupon-cash {
.coupon-value {
text-align: center;
margin-top: 20px;
.value {
color: #fff;
font-size: 44px;
}
}
.symbol {
color: #fff;
font-size: 24px;
}
.coupon-rule {
color: #fff;
font-size: 22px;
text-align: center;
}
}
.coupon-discount {
.coupon-value {
text-align: center;
margin-top: 20px;
.value {
color: #fff;
font-size: 44px;
}
}
.symbol {
color: #fff;
font-size: 24px;
}
.coupon-rule {
color: #fff;
font-size: 22px;
text-align: center;
}
}
}
.ba-coupon-desc {
padding: 20px;
background-color: #fff;
margin-top: 2px;
.desc-txt {
color: #555;
font-size: 22px;
}
}
}

View File

@@ -1,74 +0,0 @@
@import '@/style/imports';
.shareCSS {
// margin-top: -8rpx !important;
font-size: 22rpx !important;
text-align: center !important;
border: none !important;
padding: 0 !important;
background: #3e0f3c !important;
color: #fff;
height: 48rpx;
line-height: 48rpx;
border-radius: 30rpx;
// width: 170rpx;
&.disabled {
background: #d3d3d3 !important;
}
}
.coupon-btn {
opacity: 1 !important;
}
.shareCSS:after {
border: none;
}
.coupon-list {
/* #ifdef h5 */
padding-top: $navigate-height-h5;
/* #endif */
.at-tabs__header {
position: absolute;
top: $navigate-height;
/* #ifdef h5 */
top: $navigate-height-h5;
/* #endif */
width: 100%;
z-index: $z-index-toolbar;
}
.home_coupon-list__scroll {
// height: 100vh;
@include page-scroll($tabs-height + $searchbar-height + $navigate-height, $tabbar-height);
// padding: 0 $edge-margin;
box-sizing: border-box;
}
.home_coupon-list_item {
position: relative;
}
.home_coupon-list_item__quantity {
position: absolute;
bottom: 4px;
font-size: 24px;
}
&__tabs {
position: fixed;
z-index: $z-index-toolbar;
left: 0;
height: 100px;
top: 0;
width: 100%;
}
}
.coupon-btn {
color: #ffffff;
font-size: 24px;
height: 50px;
line-height: 50px;
border-radius: 50px;
// padding: 0 10px;
&__done {
// background: #c4c4c4 !important;
color: #ffffff;
opacity: 0.8;
}
}

View File

@@ -1,10 +1,17 @@
import React, { useEffect } from 'react'
import { useSelector } from 'react-redux'
import { useImmer } from 'use-immer'
import Taro, { getCurrentInstance, useDidShow } from '@tarojs/taro'
import { View } from '@tarojs/components'
import Taro, {
getCurrentInstance,
useDidShow,
useShareAppMessage,
useShareTimeline
} from '@tarojs/taro'
import { View, Button } from '@tarojs/components'
import { SpPage, SpScrollView, CouponItem } from '@/components'
import api from '@/api'
import doc from '@/doc'
import { pickBy } from '@/utils'
import {
BaHomeWgts,
BaStoreList,
@@ -21,6 +28,7 @@ const initialState = {
}
function GuideCouponIndex(props) {
const $instance = getCurrentInstance()
const { subtask_id = '' } = getCurrentInstance().router.params
const [state, setState] = useImmer(initialState)
const { list } = state
const { userInfo } = useSelector((state) => state.guide)
@@ -35,6 +43,28 @@ function GuideCouponIndex(props) {
})
})
useShareAppMessage(async (options) => {
const cardId = options.target.dataset.info
return getAppShareInfo(cardId)
})
// useShareTimeline(async (res) => {
// return getAppShareInfo()
// })
const getAppShareInfo = async (cardId) => {
const { title, imageUrl } = await api.wx.shareSetting({ shareindex: 'coupon' })
const { salesperson_id, distributor_id, work_userid, shop_code } = userInfo
const gu = `${work_userid}_${shop_code}`
const path = `/others/pages/home/coupon-home?smid=${salesperson_id}&card_id=${cardId}&distributor_id=${distributor_id}&subtask_id=${subtask_id}&gu=${gu}`
console.log(`getAppShareInfo:`, path)
return {
title: title,
imageUrl: imageUrl,
path: path
}
}
const fetch = async () => {
const { card_id = '', item_id = '' } = $instance.router.params
const { distributor_id } = userInfo
@@ -45,9 +75,9 @@ function GuideCouponIndex(props) {
item_id
}
const { list, total_count } = await api.member.homeCouponList(params)
console.log(pickBy(list, doc.coupon.COUPON_ITEM))
setState((draft) => {
draft.list = list
draft.list = pickBy(list, doc.coupon.COUPON_ITEM)
})
return { total: total_count }
}
@@ -55,12 +85,14 @@ function GuideCouponIndex(props) {
return (
<SpPage className='page-guide-coupon'>
<BaNavBar home title='优惠券' />
<SpScrollView fetch={fetch}>
<SpScrollView className='coupon-list' fetch={fetch}>
{list.map((item) => (
// <CouponItem info={item} />
<BaCoupon />
<View className='coupon-item__wrap'>
<BaCoupon info={item} />
</View>
))}
</SpScrollView>
<BaTabBar />
</SpPage>
)
}

View File

@@ -1,2 +1,10 @@
.page-guide-coupon {
.coupon-list {
padding: 20px;
.coupon-item__wrap {
&:not(:last-child) {
margin-bottom: 20px;
}
}
}
}

View File

@@ -0,0 +1,191 @@
import React, { Component } from 'react'
import Taro, { getCurrentInstance } from '@tarojs/taro'
import { View, ScrollView } from '@tarojs/components'
import { withPager, withBackToTop } from '@/hocs'
import { SearchBar, RecommendItem, SpNote, Loading } from '@/components'
import { BaTabBar, BaNavBar } from '../components'
import api from '@/api'
import S from '@/subpages/guide/lib/Spx.js'
import { pickBy, styleNames } from '@/utils'
import './list.scss'
@withPager
@withBackToTop
export default class RecommendList extends Component {
constructor(props) {
super(props)
this.state = {
...this.state,
query: null,
list: [],
isShowSearch: false
}
}
async componentDidMount() {
// await S.autoLogin(this)
this.nextPage()
}
config = {
navigationBarTitleText: '种草',
navigationStyle: 'custom'
}
componentDidShow() {}
// 搜索查询
handleSearchOn = () => {
this.setState({
isShowSearch: true
})
}
handleSearchOff = () => {
this.setState({
isShowSearch: false
})
}
handleSearchChange = (val) => {
this.setState({
query: {
...this.state.query,
title: val
}
})
}
handleSearchClear = () => {
this.setState(
{
isShowSearch: false,
query: {
...this.state.query,
title: ''
}
},
() => {
this.resetPage()
this.setState(
{
list: []
},
() => {
this.nextPage()
}
)
}
)
}
handleConfirm = (val) => {
this.setState(
{
isShowSearch: false,
query: {
...this.state.query,
title: val
}
},
() => {
this.resetPage()
this.setState(
{
list: []
},
() => {
this.nextPage()
}
)
}
)
}
async fetch(params) {
const { page_no: page, page_size: pageSize } = params
const article_query = {
article_type: 'bring',
...this.state.query,
page,
pageSize
}
const { list, total_count: total } = await api.article.list(article_query)
if (list.length) {
const nList = pickBy(list, {
img: 'image_url',
item_id: 'article_id',
title: 'title',
author: 'author',
summary: 'summary',
head_portrait: 'head_portrait',
isPraise: 'isPraise',
articlePraiseNum: 'articlePraiseNum.count'
})
this.setState({
list: [...this.state.list, ...nList]
})
}
return {
total
}
}
handleClickItem = (item) => {
const url = `/subpages/guide/recommend/detail?id=${item.item_id}`
Taro.navigateTo({
url
})
}
render() {
const { query, isShowSearch, scrollTop, list, page } = this.state
const n_ht = S.get('navbar_height', true)
const c_ht = n_ht + 42
return (
<View className='guide-recommend-list'>
<BaNavBar title='种草' fixed />
<View style={styleNames({ height: `${n_ht}px` })}></View>
<View
className={`recommend-list__search ${
query && query.title && isShowSearch ? 'on-search' : null
}`}
>
<SearchBar
showDailog={false}
keyword={query ? query.title : ''}
onFocus={this.handleSearchOn}
onChange={this.handleSearchChange}
onClear={this.handleSearchClear}
onCancel={this.handleSearchOff}
onConfirm={this.handleConfirm.bind(this)}
/>
</View>
<ScrollView
className='recommend-list__scroll'
scrollY
scrollTop={scrollTop}
scrollWithAnimation
onScroll={this.handleScroll}
onScrollToLower={this.nextPage}
style={styleNames({ top: `${c_ht}px` })}
>
<View className='recommend-list recommend-list__type-grid'>
{list.map((item) => {
return (
<View className='recommend-list__item' key={item.item_id}>
<RecommendItem info={item} onClick={() => this.handleClickItem(item)} noShowZan />
</View>
)
})}
</View>
{page.isLoading ? <Loading>正在加载...</Loading> : null}
{!page.isLoading && !page.hasNext && !list.length && (
<SpNote img='trades_empty.png'>暂无数据~</SpNote>
)}
</ScrollView>
<BaTabBar />
</View>
)
}
}

View File

@@ -0,0 +1,104 @@
@import '@/style/imports.scss';
.guide-recommend-list {
.recommend-list__search {
background-color: #fff;
height: 85rpx;
}
.recommend-list {
&__toolbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: $z-index-toolbar;
background: #fff;
box-shadow: $box-shadow;
padding-top: 10px;
.at-search-bar {
padding-right: 30px !important;
}
.search-input {
box-shadow: none;
&__focus {
.at-search-bar {
padding-right: 30px !important;
}
}
}
.at-search-bar__input {
height: $searchbar-height !important;
}
.at-search-bar__input-cnt {
flex: none;
border-radius: $searchbar-height;
}
.at-search-bar__clear {
height: $searchbar-height;
}
.at-search-bar__action {
display: none;
}
.filter-icon {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100px;
font-size: 20px;
.icon-list {
font-size: 55px;
line-height: 0.8;
}
}
}
&__tabs {
display: flex;
.filter-bar__item {
flex: 1;
justify-content: center;
text-align: center;
color: #666666;
font-size: 26px;
[class^='icon'] {
color: #ccc;
display: inline-block;
}
&.region-picker {
display: flex;
line-height: 75rpx;
}
.icon-close {
line-height: 75px;
}
}
.filter-bar__item-active {
color: $color-brand-primary;
}
}
&__scroll {
@include page-scroll(
$tabs-height + $searchbar-height + $navigate-height + 10,
$tabbar-height + floor($edge-margin / 2)
);
}
&__type-grid {
display: flex;
flex-wrap: wrap;
.recommend-list__item {
width: 50%;
padding: 10px;
box-sizing: border-box;
}
}
}
&__search {
position: relative;
&.on-search {
.at-search-bar {
padding-right: 0 !important;
}
}
}
}

View File

@@ -23,7 +23,7 @@ export default class RecommendList extends Component {
}
async componentDidMount() {
await S.autoLogin(this)
// await S.autoLogin(this)
this.nextPage()
}

View File

@@ -159,6 +159,7 @@ function CompPackageItem(props) {
hideInputNumber
open={skuPanelOpen}
info={skuInfo}
type='picker'
onClose={() => {
setState((draft) => {
draft.skuPanelOpen = false