mirror of
https://gitee.com/ShopeX/ECShopX_mobile-frontend
synced 2026-08-14 17:41:45 +08:00
结算
This commit is contained in:
@@ -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)
|
||||
}
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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)
|
||||
|
||||
341
src/pages/cart/espier-checkout.js
Normal file
341
src/pages/cart/espier-checkout.js
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
||||
153
src/pages/cart/espier-checkout.scss
Normal file
153
src/pages/cart/espier-checkout.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user