This commit is contained in:
bentz
2019-03-07 20:24:54 +08:00
parent d65cb1e576
commit de1bfba92d
8 changed files with 561 additions and 19 deletions

View File

@@ -1,4 +1,3 @@
import qs from 'qs'
import req from './req'
export function get (params) {
@@ -20,14 +19,12 @@ export function getBasic (params) {
export function add (item, num = 1) {
// return req.post('/cart.add', { sku_id, quantity })
const { item_id, shop_id } = item
const q = qs.stringify({
return req.post(`http://pjj.aixue7.com/index.php/api/h5app/wxapp/cart`, {
item_id,
shop_id,
num,
shop_type: 'distributor',
activity_type: 'normal'
shop_type: 'distributor'
})
return req.get(`http://pjj.aixue7.com/index.php/api/h5app/wxapp/cart?${q}`)
}
export function update ({ cart_params }) {
@@ -41,3 +38,8 @@ export function del ({ cart_id }) {
export function checkout () {
return req.get('/cart.checkout')
}
export function total (params) {
// return req.post('/cart.total')
return req.post('http://pjj.aixue7.com/index.php/api/h5app/wxapp/getFreightFee', params)
}

View File

@@ -2,9 +2,9 @@ import Taro from '@tarojs/taro'
import S from '@/spx'
import qs from 'qs'
// function addQuery (url, query) {
// return url + (url.indexOf('?') >= 0 ? '&' : '?') + query
// }
function addQuery (url, query) {
return url + (url.indexOf('?') >= 0 ? '&' : '?') + query
}
class API {
constructor (options = {}) {
@@ -65,6 +65,13 @@ class API {
...(options.data || {}),
company_id: 1
}
if (options.method === 'GET') {
options.url = addQuery(options.url, qs.stringify(options.data))
delete options.data
} else {
// nest data
options.data = qs.stringify(options.data)
}
return Taro.request(options)
.then(res => {

View File

@@ -25,7 +25,7 @@ class App extends Component {
'pages/item/point-detail',
'pages/cart/index',
'pages/cart/checkout',
'pages/cart/espier-checkout',
'pages/article/index',
'pages/category/index',

View File

@@ -4,6 +4,7 @@ import { connect } from '@tarojs/redux'
import { AtTabBar } from 'taro-ui'
import api from '@/api'
import { navigateTo, getCurrentRoute } from '@/utils'
import S from '@/spx'
@connect(({ cart }) => ({
cart,
@@ -50,6 +51,8 @@ export default class TabBar extends Component {
}
async fetchCart () {
if (!S.getAuthToken()) return
try {
const { list } = await api.cart.getBasic()
this.props.onUpdateCart(list)

View File

@@ -0,0 +1,341 @@
import Taro, { Component } from '@tarojs/taro'
import { View, Text, Image, ScrollView, Switch } from '@tarojs/components'
import { connect } from '@tarojs/redux'
import { AtButton, AtInput, AtActionSheet, AtActionSheetItem } from 'taro-ui'
import { Loading, Price, SpCell, AddressPicker } from '@/components'
import api from '@/api'
import { lockScreen } from '@/utils/dom'
import CheckoutItems from './checkout-items'
import './checkout.scss'
@connect(({ cart }) => ({
fastbuy: cart.fastbuy
}), (dispatch) => ({
onClearFastbuy: () => dispatch({ type: 'cart/clearFastbuy' })
}))
export default class CartCheckout extends Component {
constructor (props) {
super(props)
this.state = {
info: null,
address: null,
showShippingPicker: false,
showAddressPicker: false,
showCheckoutItems: false,
curCheckoutItems: null,
total: {
items_count: '',
total_fee: '0.00',
item_fee: '',
member_discount: '',
coupon_discount: '',
freight_fee: ''
}
}
}
componentDidMount () {
this.fetch()
}
async fetch () {
// const { point_total: { point_count: pointTotal } } = await api.member.pointDetail()
// const { cartInfo: info, total, default_address: address } = await api.cart.checkout()
const { cart_type } = this.$router.params
let info = null
if (cart_type === 'fastbuy') {
const fastBuyItem = this.props.fastbuy
info = {
cart: [{
list: [fastBuyItem],
cart_total_num: fastBuyItem.num,
cart_total_price: (fastBuyItem.price * fastBuyItem.num / 100).toFixed(2)
}]
}
this.setState({
info
})
} else {
this.props.onClearFastbuy()
}
let total_fee = 0
let items_count = 0
const items = info.cart[0].list.map((item) => {
const { item_id, num } = item
total_fee += +(item.price)
items_count += +(item.num)
return {
item_id,
num
}
})
this.params = {
items,
receipt_type: 'logistics',
order_type: 'normal',
promotion: 'normal',
member_discount: false
}
this.setState({
total: {
items_count,
total_fee: total_fee.toFixed(2)
}
})
}
getParams () {
const { name: receiver_name, mobile: receiver_mobile, zip: receiver_zip, addrdetail: receiver_address } = this.state.address
const params = {
...this.params,
receiver_name,
receiver_mobile,
receiver_state: '浙江省',
receiver_city: '杭州市',
receiver_district: '上城区',
receiver_address,
receiver_zip: receiver_zip || '2100000'
}
return params
}
async calcOrder () {
const params = this.getParams()
const data = await api.cart.total(params)
const { item_fee, member_discount = 0, coupon_discount = 0, freight_fee = 0, total_fee } = data
const total = {
...this.state.total,
item_fee,
member_discount,
coupon_discount,
freight_fee,
total_fee
}
this.setState({
total
})
}
handleAddressChange = (address) => {
this.setState({
address
}, () => {
this.calcOrder()
})
if (!address) {
this.setState({
showAddressPicker: true
})
}
}
handleShippingChange = (type) => {
console.log(type)
}
handleClickItems (items) {
this.setState({
curCheckoutItems: items
})
this.toggleCheckoutItems()
}
toggleAddressPicker (isOpend) {
if (isOpend === undefined) {
isOpend = !this.state.showAddressPicker
}
lockScreen(isOpend)
this.setState({ showAddressPicker: isOpend })
}
toggleCheckoutItems (isOpend) {
if (isOpend === undefined) {
isOpend = !this.state.showCheckoutItems
}
lockScreen(isOpend)
this.setState({ showCheckoutItems: isOpend })
}
render () {
const { info, address, total, showShippingPicker, showAddressPicker, showCheckoutItems, curCheckoutItems } = this.state
if (!info) {
return <Loading />
}
return (
<View className='page-checkout'>
<ScrollView
scrollY
className='checkout__wrap'
>
<View
className='address-info'
onClick={this.toggleAddressPicker.bind(this, true)}
>
<SpCell
isLink
icon='map-pin'
>
{
address
? <View className='address-info__bd'>
<Text className='address-info__receiver'>
收货人{address.name} {address.mobile}
</Text>
<Text className='address-info__addr'>
收货地址{address.addrdetail}
</Text>
</View>
: <View className='address-info__bd'>请选择收货地址</View>
}
</SpCell>
</View>
<View className='cart-list'>
{
info.cart.map(cart => {
return (
<View
className='cart-group'
key={cart.shop_id}
>
<View className='cart-group__shop'>{cart.shop_name}</View>
<View className='sec cart-group__cont'>
<SpCell
className='trade-items'
value={`${cart.cart_total_num}件商品`}
// onClick={this.handleClickItems.bind(this, cart.items)}
>
<View className='trade-items__bd'>
{
cart.list.map((item, idx) => {
return (
<Image
key={idx}
className='trade-item__img'
mode='aspectFill'
src={Array.isArray(item.pics) ? item.pics[0] : item.pics }
/>
)
})
}
{cart.list.length === 1 && (
<Text className='trade-item__title'>{cart.list[0].item_name}</Text>
)}
</View>
</SpCell>
<SpCell
className='sec trade-remark'
border={false}
>
<AtInput
className='trade-remark__input'
placeholder='给商家留言选填50字以内'
/>
</SpCell>
</View>
</View>
)
})
}
</View>
{/*<View className='sec trade-point'>
<SpCell
title='积分'
border={false}
>
<View className='trade-point__wrap'>
<Text className='trade-point__hint'>可用1000积分(每1积分抵扣1元)可抵扣 <Price value={pointPrice} /></Text>
<Switch
checked
value={usePoint}
onChange={this.handlePointChange}
/>
</View>
</SpCell>
<AtInput
className='trade-point__input'
type='text'
value={point}
placeholder='全部抵扣或在此输入积分数'
/>
</View>
<SpCell
className='trade-invoice'
title='申请发票'
>
<Switch
checked
/>
</SpCell>*/}
<View className='sec trade-sub-total'>
<SpCell
className='trade-sub-total__item'
title='商品金额'
>
<Price value={total.item_fee} />
</SpCell>
<SpCell
className='trade-sub-total__item'
title='运费'
>
<Price value={total.freight_fee}></Price>
</SpCell>
<SpCell
className='trade-sub-total__item'
title='优惠券'
>
<Price value={total.coupon_discount} />
</SpCell>
</View>
</ScrollView>
<AddressPicker
isOpend={showAddressPicker}
value={address}
onChange={this.handleAddressChange}
onClickBack={this.toggleAddressPicker.bind(this, false)}
/>
<CheckoutItems
isOpend={showCheckoutItems}
list={curCheckoutItems}
onClickBack={this.toggleCheckoutItems.bind(this, false)}
/>
<AtActionSheet
isOpend={showShippingPicker}
onClose={() => this.setState({ showShippingPicker: false })}
>
<AtActionSheetItem onClick={this.handleShippingChange}>顺丰</AtActionSheetItem>
<AtActionSheetItem onClick={this.handleShippingChange}>自提</AtActionSheetItem>
</AtActionSheet>
<View className='toolbar checkout-toolbar'>
<View className='checkout__total'>
<Text className='total-items'>{total.items_count}</Text>件,合计: <Price primary value={total.total_fee} />
</View>
<AtButton
circle
type='primary'
className='btn-confirm-order'
>提交订单</AtButton>
</View>
</View>
)
}
}

View File

@@ -0,0 +1,153 @@
@import '../../style/imports';
.page-checkout {
.checkout {
&__wrap {
height: 100vh;
box-sizing: border-box;
padding-bottom: $toolbar-height;
}
&__total {
margin-right: 24px;
}
&-toolbar {
display: flex;
justify-content: flex-end;
}
}
.address-info {
margin: 0 0 $edge-margin;
&__receiver {
color: #111;
display: block;
font-size: $font-size-large;
margin: 0 0 16px;
line-height: 1;
}
&__addr {
color: #111;
line-height: 1;
display: block;
}
}
.sec-checkout-items {
padding: $edge-margin $edge-size $edge-size;
.sp-cell {
padding-left: 0;
padding-right: 0;
}
}
.cart-group {
&__shop {
padding: 16px $edge-margin;
}
&__cont {
padding-bottom: 0;
}
.at-input {
&:after {
border: none;
}
}
}
.trade-items {
display: flex;
&__bd {
display: flex;
align-items: center;
max-width: 68%;
}
}
.trade-item {
&__img {
width: 120px;
height: 120px;
margin-right: 20px;
}
&__title {
}
}
.trade-shipping, .trade-invoice, .trade-remark, .trade-point, .trade-sub-total {
margin: 0 0 $edge-margin;
}
.trade-point {
padding: 0 $edge-size $edge-margin;
.sp-cell {
padding-left: 0;
padding-right: 0;
}
&__wrap {
display: flex;
align-items: center;
justify-content: flex-end;
}
&__hint {
color: $color-brand-primary;
font-size: $font-size-small;
}
&__input {
background: $color-bg-gray;
border-radius: 12px;
height: 80px;
line-height: 80px;
box-sizing: border-box;
font-size: $font-size;
border: none;
box-shadow: none;
margin: 0;
}
switch {
margin-left: 20px;
}
.at-input {
&:after {
border: none;
}
input {
padding-left: $edge-size;
}
}
}
.trade-invoice {
.sp-cell__bd {
display: flex;
justify-content: flex-end;
}
}
.trade-remark {
padding: $edge-margin $edge-size;
&__input {
box-sizing: border-box;
padding: 0;
background: none;
box-shadow: none;
border: none;
}
}
.trade-sub-total {
padding: $edge-margin 0;
&__item {
padding-top: 8px;
padding-bottom: 8px;
}
.sp-cell {
&:before {
border: none;
}
}
.sp-cell__bd {
color: $color-brand-primary;
display: flex;
justify-content: flex-end;
}
}
}

View File

@@ -1,7 +1,8 @@
import Taro, { Component } from '@tarojs/taro'
import { View, Text, ScrollView, Swiper, SwiperItem, Image } from '@tarojs/components'
import { connect } from '@tarojs/redux'
import { AtDivider, AtCountdown } from 'taro-ui'
import { Loading, Price, BackToTop, SpHtmlContent } from '@/components'
import { Loading, Price, BackToTop, SpHtmlContent, SpToast } from '@/components'
import api from '@/api'
import { withBackToTop } from '@/hocs'
import { styleNames, log } from '@/utils'
@@ -10,6 +11,11 @@ import GoodsBuyToolbar from './comps/buy-toolbar'
import './espier-detail.scss'
@connect(({ cart }) => ({
cart
}), (dispatch) => ({
onFastbuy: (item) => dispatch({ type: 'cart/fastbuy', payload: { item } })
}))
@withBackToTop
export default class Detail extends Component {
static options = {
@@ -109,7 +115,7 @@ export default class Detail extends Component {
handleBuyClick = async (type) => {
const { marketing, info } = this.state
let url = `/pages/cart/checkout`
let url = `/pages/cart/espier-checkout`
const hasToken = !!S.getAuthToken()
if (!hasToken) {
@@ -117,19 +123,27 @@ export default class Detail extends Component {
}
if (type === 'cart') {
await api.cart.add(info)
return Taro.navigateTo({
url
})
const data = await api.cart.add(info)
if (data.cart_id) {
return Taro.navigateTo({
url
})
} else {
S.toast('加入购物车失败,请稍后再试')
}
}
if (type === 'fastbuy') {
url += '?cart_type=fastbuy'
if (marketing === 'group') {
url = `/pages/cart/checkout?type=${marketing}&group_id=${this.state.info.group_activity.groups_activity_id}`
url += `&type=${marketing}&group_id=${this.state.info.group_activity.groups_activity_id}`
} else if (marketing === 'seckill') {
url = `/pages/cart/checkout?type=${marketing}&seckill_id=${this.state.info.seckill_activity.seckill_id}`
url += `&type=${marketing}&seckill_id=${this.state.info.seckill_activity.seckill_id}`
}
return Taro.navigateTo({
this.props.onFastbuy(info)
Taro.navigateTo({
url
})
}
@@ -315,6 +329,8 @@ export default class Detail extends Component {
onClickAddCart={this.handleBuyClick.bind(this, 'cart')}
onClickFastBuy={this.handleBuyClick.bind(this, 'fastbuy')}
/>
<SpToast />
</View>
)
}

View File

@@ -1,8 +1,9 @@
import { createReducer } from 'redux-create-reducer'
import { pickBy } from '@/utils'
const initState = {
list: [],
checkoutItem: null
fastbuy: null
}
const cart = createReducer(initState, {
@@ -22,6 +23,25 @@ const cart = createReducer(initState, {
...state,
checkoutItem
}
},
['cart/fastbuy'](state, action) {
const { item , num = 1 } = action.payload
return {
...state,
fastbuy: {
...item,
num
}
}
},
['cart/clearFastbuy'](state) {
return {
...state,
fastbuy: null
}
}
})