Commit 70d2b1ac by xuzhenghua

pull

parent 98d7e8e9
import React from 'react'
import { Modal } from 'antd-mobile'
import './index.scss'
export default function ({
amount,
limit_amount,
onCancel = () => {
},
onConfirm
}) {
const content = (
<>
<div className="end-expansion-alert-ques">
{`你的${amount}元优惠券正在膨胀中,
确定要结束膨胀吗?`}
</div>
<div className="end-expansion-alert-hint">
{`离${limit_amount}元只差一点点了!继续膨胀,优惠更多哦`}
</div>
</>
)
Modal.alert('温馨提示', content, [
{text: '再考虑下', onPress: onCancel, style: {color: '#333'}},
{text: '确定结束膨胀', onPress: onConfirm}
])
}
.am-modal {
width: 300px;
&-title {
font-size: 15px;
}
}
.end-expansion-alert {
&-ques {
width: 200px;
margin: 0 auto 20px;
text-align: center;
color: #666;
font-size: 15px;
}
&-hint {
color: #999;
font-size: 12px;
}
}
import React, {Component} from 'react'
import './index.scss'
import {http} from '@/utils'
import { Link } from "react-router-dom"
import {Toast} from "antd-mobile";
class ExpandActiveToast extends Component {
constructor(props) {
super(props);
this.state = {
expandLength: 0,
isShowExpand:true
}
}
componentDidMount() {
http.get(`${API['base-api']}/sys/deposit/notice`).then((res) => {
if (res.data.errno == 200) {
const {data} = res.data
this.setState({
expandLength: data.num
})
} else {
Toast.info(res.data.msg, 2)
}
})
}
cleseExpand = () => {
this.setState({isShowExpand: false})
}
render() {
return (
<div>
{
this.state.expandLength > 0 && this.state.isShowExpand &&
<div className="expand-active-toast">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/guanggao.png" alt=''/>
<div className="expand-toast-swiper">
<p>您有<span className="red">{this.state.expandLength}</span>待支付尾款的课程 再不支付就要过期了!</p>
</div>
<Link to='/final-deposit-order?source=1'>查看</Link>
<img
onClick={e => this.cleseExpand()}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/guanbi.png"
alt=''
/>
</div>
}
</div>
);
}
}
export default ExpandActiveToast
.expand-active-toast {
font-size: 14px;
background-color: #e8f6ff;
display: flex;
justify-content: space-between;
padding: 0 15px;
height: 33px;
line-height: 33px;
margin-bottom: 10px;
.expand-toast-swiper {
width: 240px;
overflow: hidden;
position: relative;
p {
width: 375px;
position: absolute;
-webkit-animation: scollLeft 10s linear 0s infinite;
}
}
.red {
color: #ff3131;
}
img {
width: 15px;
height: 15px;
margin-top: 9px;
}
a {
display: inline-block;
width: 44px;
height: 22px;
background: linear-gradient(90deg, #0099ff 0%, #0080ff 100%);
border-radius: 11px;
color: #fff;
font-size: 12px;
line-height: 22px;
margin-top: 5px;
text-align: center;
}
@-webkit-keyframes scollLeft {
from {
right: -100%;
}
to {
right: 100%;
}
}
@keyframes scollLeft {
from {
right: -100%;
}
to {
right: 100%;
}
}
@-moz-keyframes scollLeft {
from {
right: -100%;
}
to {
right: 100%;
}
}
@-o-keyframes scollLeft {
from {
right: -100%;
}
to {
right: 100%;
}
}
}
......@@ -11,6 +11,7 @@ import { Link } from "react-router-dom"
import { Toast } from 'antd-mobile'
import { connect } from "react-redux";
import TopSwiper from './TopSwiper'
import ExpandActiveToast from './expandActiveToast'
// const animateTypes = Swiper.animateTypes
......@@ -135,6 +136,10 @@ class Index extends Component {
/>
</div>
<div className='zw_height'></div>
<ExpandActiveToast/>
<div className='index-swiper'>
{
this.state.banner && this.state.banner.length > 0 &&
......
......@@ -38,8 +38,11 @@
}
}
.zw_height {
height: 44px;
}
.index-swiper {
margin-top: 44px;
height: 168px;
.swiper-container {
......
import React, { Component } from 'react';
import { http } from '@/utils';
import React, {Component} from 'react';
import {http} from '@/utils';
import listFrame from './../listFrame/index';
import './index.scss';
import {Toast} from "antd-mobile"
import {connect} from "react-redux";
import {Link, withRouter} from "react-router-dom"
class ReserveCourse extends Component {
constructor(props) {
super(props);
this.state = {
};
}
componentDidMount() {
this.fetchAICourse();
}
fetchAICourse = (key) => {
const { basic, advanced, higher, expand } = this.state;
http.get(`${API.home}/sys/ai_grow_up_courses/${key}`).then(res => {
const {code, data} = res.data;
if (code === 200) {}
});
}
render() {
const { basic} = this.state;
return (
<div className='reserve-course-module'>
constructor(props) {
super(props);
this.state = {
courseData: []
};
}
</div>
)
}
componentDidMount() {
this.fetchAICourse();
}
fetchAICourse = () => {
http.get(`${API.home}/sys/pre_coursee`).then(res => {
const {code, data, msg} = res.data;
if (code === 200) {
this.setState({
courseData: data
})
} else {
Toast.info(msg, 2);
}
});
}
// 立即付定金
expandPaydj = (courseId) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
this.props.history.push(
`/deposit-order?oid=${courseId}&source=${1}`,
{
id: courseId,
isexpand: 1,
sourcenum: 1
}
)
}
}
// 立即付尾款
expandPaywk = (courseId, day) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
Toast.info("付尾款时间将在" + day + "开启", 2);
}
}
// 去学习
tostudy = (courseId) => {
this.props.history.push(`/getDetail?id=${courseId}`)
}
render() {
const {courseData} = this.state;
return (
<div className='reserve-course-module'>
<CourseList courseData={courseData}
expandPaydj={this.expandPaydj}
expandPaywk={this.expandPaywk}
tostudy={this.tostudy}/>
</div>
)
}
}
function courseList() {
function CourseList(props) {
const {courseData, expandPaydj, expandPaywk, tostudy} = props
return (
<div className="course-list">
<ul>
{
courseData.map((item, index) => {
return (
<li className="course-item-box" key={index}>
<Link to={`/getDetail?id=${item.course_id}`}>
<div className="top">
<div className="square">
<p className="circular">
到手最低¥<span>{Number(item.price) - Number(item.deduction_amount) - Number(item.limit_amount)}</span>
</p>
</div>
<img className="course-img" src={item.image_name} alt=""/>
</div>
</Link>
<p className="count-price">
=原价¥{item.price}
<span>-抵扣¥<i>{item.deduction_amount}</i></span>
<span>-膨胀券¥<i>{item.limit_amount}</i></span>
</p>
<div className="btn">
{
item.is_buy === 0 &&
<button className="to-expand-buy1"
onClick={() => expandPaydj(item.course_id)}>立即付定金</button>
}
{
item.is_buy === 1 &&
<button className="to-expand-buy2"
onClick={() => expandPaywk(item.course_id, item.final_start_time)}>立即付尾款</button>
}
{
item.is_buy === 2 &&
<button className="to-study"
onClick={() => tostudy(item.course_id)}>开始学习</button>
}
</div>
</li>
)
})
}
</ul>
</div>
)
}
export default listFrame(ReserveCourse);
\ No newline at end of file
export default listFrame(connect(
state => ({
user: state.user
}),
)(withRouter(ReserveCourse)))
\ No newline at end of file
.reserve-course-module {
margin: 20px 15px 5px 20px;
.course-list {
ul {
display: flex;
justify-content: space-between;
flex-direction: row;
flex-wrap: wrap;
.course-item-box {
width: 48%;
padding: 4px;
background-color: #fff;
border-radius: 2px;
margin-bottom: 15px;
text-align: left;
.top {
width: 100%;
height: 108px;
position: relative;
.course-img {
width: 100%;
height: 108px;
}
.square {
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/course-label-bg.png");
background-repeat: no-repeat;
background-size: cover;
width: 60px;
height: 60px;
position: absolute;
left: 0;
bottom: 0;
.circular {
height: 100%;
width: 100%;
color: #fff;
padding-top: 15px;
text-align: left;
padding-left: 5px;
span {
font-size: 16px;
margin-left: 3px;
}
}
}
}
.count-price {
text-align: left;
color: #555;
margin-top: 8px;
line-height: 15px;
span {
color: #FF4000;
i {
font-size: 16px;
font-style: normal;
margin-left: 3px;
}
}
}
.btn {
width: 100%;
padding: 0 5px;
margin-top: 8px;
margin-bottom: 5px;
button {
width: 100%;
height: 24px;
border-radius: 2px;
font-size: 12px;
color: #fff;
border: none;
}
.to-expand-buy1 {
background: linear-gradient(-90deg, #7800FF 0%, #FF4BF0 100%);
}
.to-expand-buy2 {
background: linear-gradient(-90deg, #FF8C1B 0%, #FF3B05 100%);
}
.to-study {
background: linear-gradient(-90deg, #2ECEF0 0%, #2D56F0 100%);
}
}
}
}
}
}
$bg_type1: #FE6161;
$bg_type2: #E0B97B;
$bg_voucher: #FE6161;
$bg_free: #E0B97B;
$bg_expand: #8361FE;
.coupon {
position: relative;
margin-bottom: 15px;
......@@ -27,13 +28,14 @@ $bg_type2: #E0B97B;
}
}
.course-title{
.course-title {
width: 68.37%;
margin: 0 auto 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: $font_16;
text-align: center;
}
.expire {
......@@ -43,14 +45,18 @@ $bg_type2: #E0B97B;
}
&.coupon-type1 {
background: $bg_type1;
background: $bg_voucher;
}
&.coupon-type2 {
background: $E0B97B;
}
&.invalid{
&.coupon-type4 {
background: $bg_expand;
}
&.invalid {
background: $color_999;
}
......@@ -87,6 +93,44 @@ $bg_type2: #E0B97B;
transform: translateY(50%);
}
}
.progress-container {
width: 299px;
margin: 0 auto;
.denomination {
font-size: 15px;
line-height: 1.3em;
color: #F8E71C;
span{
transform: scale(0.9);
}
}
.progress-bar-container {
position: relative;
height: 7px;
background: #5C2FFF;
border-radius: 4px;
overflow: hidden;
margin-bottom: 6px;
.progress-bar {
position: absolute;
left: 0;
top: 0;
height: 100%;
background: #F8E71C;
border-radius: 4px;
}
}
.money {
display: flex;
justify-content: space-between;
}
}
}
.coupon-des {
......@@ -117,5 +161,15 @@ $bg_type2: #E0B97B;
background: transparent;
-webkit-appearance: none;
}
.stop-expanding {
padding: 3px 8px;
border: 1px solid #FF3131;
border-radius: 10px;
-webkit-appearance: none;
background: transparent;
color: #FF3131;
font-size: 10px;
}
}
}
\ No newline at end of file
}
import React, { PureComponent } from 'react'
import './coupon.scss'
import classnames from 'classnames'
import { http } from "@/utils"
import showAlert from '@common/deposit/end-expansion-alert'
import {Toast} from 'antd-mobile'
class Coupon extends PureComponent {
VOUCHER = 1 //代金券
FREE = 2 //免单券
EXPAND = 4 //膨胀全
pick = () => {
let {useCoupon, invalid} = this.props
!invalid && useCoupon && useCoupon(this.props.id)
......@@ -14,73 +22,191 @@ class Coupon extends PureComponent {
this.props.useCoupon(this.props.id)
}
ExchangeCourse = (e) => {
this.props.toExchangeCourse(e,this.props.code)
this.props.toExchangeCourse(e, this.props.code)
}
stopExpanding = (id, e) => {
const {amount, limit_amount} = this.props
e.stopPropagation()
showAlert({
amount,
limit_amount,
onConfirm: () => {
http.post(`${API.home}/m/end_expansion`, {
id
})
.then(res => {
const {data} = res
if (data.code == 200) {
this.props.endExpansion(id)
}else {
Toast.info(data.msg)
}
})
}
})
}
render() {
let {
ctype,
amount,
format_expire_time,
limit_course,
invalid,
course_title,
showUseButton,
id,
code,
selectedCouponId,
showUseButton
format_expire_time,
start_amount,
limit_amount
} = this.props
return (
<li className='coupon' onClick={this.pick}>
<div className={classnames('coupon-info', invalid ? 'invalid' : `coupon-type${ctype}`)}>
<p className='type'>{ctype === 1 ? '代金券' : '课程券'}</p>
{
ctype === 1 ? <p className='denomination'>{amount} <span></span></p>
: <p className='course-title'>{course_title}</p>
let top, bottom
}
<p className='expire'>有效期至:{format_expire_time}</p>
{
selectedCouponId === id &&
<i className={classnames('iconfont icondanseshixintubiao-5', {
check: !invalid
})}
/>
}
<ul>
switch (ctype) {
case this.VOUCHER:
top = (
<>
<p className='denomination'>{amount} <span></span></p>
<p className='expire'>有效期至:{format_expire_time}</p>
</>
)
bottom = (
<>
<span className={'limit'}>可用于大于代金券金额的课程</span>
{
new Array(19).fill('a').map((item, index) => {
return <li key={index}/>
})
showUseButton && ctype == this.VOUCHER &&
<button
className='use'
onClick={this.GoToUse}
>立即使用
</button>
}
</ul>
</div>
<div className="coupon-des">
<span className='limit'>{
limit_course === 0 ? '可用于大于代金券金额的课程' : `仅适用于《${course_title}》`
}</span>
{
showUseButton && ctype == 1 &&
<button
className='use'
onClick={this.GoToUse}
>立即使用
</button>
}
{
showUseButton && ctype == 2 &&
<button
className='use'
onClick={(e)=>this.ExchangeCourse(e)}
>立即兑换
</button>
}
</>
)
break
case this.FREE:
top = (
<>
<p className='course-title'>{course_title}</p>
<p className='expire'>有效期至:{format_expire_time}</p>
</div>
</li>
);
</>
)
bottom = (
<>
<span className={'limit'}>{`仅适用于《${course_title}》`}</span>
{
showUseButton && ctype == this.FREE &&
<button
className='use'
onClick={(e) => this.ExchangeCourse(e)}
>立即兑换
</button>
}
</>
)
break
case this.EXPAND:
if (!start_amount) {
top = (
<>
<p className='denomination'>{amount} <span></span></p>
<p className='expire'>有效期至:{format_expire_time}</p>
</>
)
} else {
top = (
<>
<div className="progress-container">
<p className='denomination'>{amount} <span></span></p>
<div className={'progress-bar-container'}>
<span className={'progress-bar'}
style={{width: `${Math.round((amount - start_amount) / limit_amount * 100)}%`}}
></span>
</div>
<div className={'money'}>
<span>{start_amount}</span>
<span>{limit_amount}</span>
</div>
</div>
</>
)
}
bottom = (
<>
<span className={'limit'}>全场通用</span>
{
start_amount
&& <button className='stop-expanding'
onClick={this.stopExpanding.bind(this, id)}>立即结束膨胀</button>
}
</>
)
break
}
return (
<BaseCoupon
{...this.props}
top={top}
VOUCHER={this.VOUCHER}
FREE={this.FREE}
EXPAND={this.EXPAND}
pick={this.pick}
bottom={bottom}
/>
)
}
}
function BaseCoupon(
{
pick,
ctype,
invalid,
top,
VOUCHER,
FREE,
EXPAND,
selectedCouponId,
id,
bottom
}) {
let couponTypes = {
[VOUCHER]: '代金券',
[FREE]: '课程券',
[EXPAND]: '膨胀券'
}
return (
<li className='coupon' onClick={pick}>
<div className={classnames('coupon-info', invalid ? 'invalid' : `coupon-type${ctype}`)}>
<p className='type'>{couponTypes[ctype]}</p>
{top}
{
selectedCouponId === id &&
<i className={classnames('iconfont icondanseshixintubiao-5', {
check: !invalid
})}
/>
}
<ul>
{
new Array(19).fill('a').map((item, index) => {
return <li key={index}/>
})
}
</ul>
</div>
<div className="coupon-des">
{bottom}
</div>
</li>
)
}
export default Coupon
\ No newline at end of file
export default Coupon
import React, { PureComponent } from 'react'
import './coupon.scss'
import classnames from 'classnames'
class Coupon extends PureComponent {
VOUCHER = 1 //代金券
FREE = 2 //免单券
EXPAND = 4 //膨胀全
pick = () => {
let {useCoupon, invalid} = this.props
!invalid && useCoupon && useCoupon(this.props.id)
}
GoToUse = () => {
this.props.useCoupon(this.props.id)
}
ExchangeCourse = (e) => {
this.props.toExchangeCourse(e, this.props.code)
}
render() {
let {
ctype,
amount,
format_expire_time,
limit_course,
invalid,
course_title,
id,
code,
selectedCouponId,
showUseButton
} = this.props
return (
<li className='coupon' onClick={this.pick}>
<div className={classnames('coupon-info', invalid ? 'invalid' : `coupon-type${ctype}`)}>
<p className='type'>{ctype === this.VOUCHER ? '代金券' : '课程券'}</p>
{
ctype === this.VOUCHER ? <p className='denomination'>{amount} <span>元</span></p>
: <p className='course-title'>{course_title}</p>
}
<p className='expire'>有效期至:{format_expire_time}</p>
{
selectedCouponId === id &&
<i className={classnames('iconfont icondanseshixintubiao-5', {
check: !invalid
})}
/>
}
<ul>
{
new Array(19).fill('a').map((item, index) => {
return <li key={index}/>
})
}
</ul>
</div>
<div className="coupon-des">
<span className='limit'>{
limit_course === 0 ? '可用于大于代金券金额的课程' : `仅适用于《${course_title}》`
}</span>
{
showUseButton && ctype == this.VOUCHER &&
<button
className='use'
onClick={this.GoToUse}
>立即使用
</button>
}
{
showUseButton && ctype == this.FREE &&
<button
className='use'
onClick={(e) => this.ExchangeCourse(e)}
>立即兑换
</button>
}
</div>
</li>
)
}
}
function BaseCoupon(
{
pick,
ctype,
invalid,
top,
VOUCHER,
FREE,
EXPAND,
limitMessage,
bottomButton
}) {
let couponTypes = {
[VOUCHER]: '代金券',
[FREE]: '课程券',
[EXPAND]: '膨胀券'
}
return (
<li className='coupon' onClick={pick}>
<div className={classnames('coupon-info', invalid ? 'invalid' : `coupon-type${ctype}`)}>
<p className='type'>{couponTypes[ctype]}</p>
{top}
<ul>
{
new Array(19).fill('a').map((item, index) => {
return <li key={index}/>
})
}
</ul>
</div>
<div className="coupon-des">
<span className='limit'>
{limitMessage}
</span>
{bottomButton}
</div>
</li>
)
}
export default Coupon
import React, {PureComponent} from 'react';
import React, { PureComponent } from 'react'
import './index.scss'
import RedeemBar from "../RedeemBar";
import RedeemBar from "../RedeemBar"
import Coupon from '../Coupon'
import {http, getParam} from '@/utils'
import {WithFullSize} from '@/HOCs'
import {Toast} from 'antd-mobile'
import {isEmpty} from 'lodash'
import {connect} from 'react-redux';
import { http, getParam } from '@/utils'
import { WithFullSize } from '@/HOCs'
import { Toast } from 'antd-mobile'
import { isEmpty } from 'lodash'
import { connect } from 'react-redux'
@connect()
class UseCoupon extends PureComponent {
......@@ -30,7 +30,7 @@ class UseCoupon extends PureComponent {
const {state} = this.props.location
if (state && state.from) {
if (state.from === '/my') {
this.getMyCoupons();
this.getMyCoupons()
this.setState({
showUseButton: true
})
......@@ -38,7 +38,7 @@ class UseCoupon extends PureComponent {
if (!this.state.courseId) {
location.state && location.state.from ? history.replace(location.state.from) : history.goBack()
}
this.getAllCoupons();
this.getAllCoupons()
}
}
}
......@@ -50,7 +50,7 @@ class UseCoupon extends PureComponent {
// 兑换
exchange = () => {
const {location: {state = {}}} = this.props;
const {location: {state = {}}} = this.props
if (this.state.redeemCode !== '') {
http.post(`${API.home}/m/coupon/exchange`, {
code: this.state.redeemCode,
......@@ -88,7 +88,7 @@ class UseCoupon extends PureComponent {
invalid_coupons: [...this.state.invalid_coupons, coupon],
showUseButton: null,
redeemCode: ''
});
})
} else {
this.setState({
valid_coupons: [...this.state.valid_coupons, coupon],
......@@ -109,45 +109,72 @@ class UseCoupon extends PureComponent {
}
getMyCoupons = () => {
http.get(`${API.home}/m/coupon/all`)
.then(res => {
const data = res.data
if (data.code === 200) {
this.setState({
couponList: isEmpty(data.data) ? [] : data.data
})
} else {
Toast.info(data.msg)
}
Promise.all([
http.get(`${API.home}/m/coupon/all`),
http.get(`${API.home}/m/coupon/expansion`)
]).then((coupons) => {
let myCoupons = []
const [allCoupons, expansionCoupons] = coupons
const {data: all} = allCoupons
const {data: expansion} = expansionCoupons
if (all.code == 200) {
Array.isArray(all.data) && (myCoupons = myCoupons.concat(all.data))
} else {
Toast.info(all.msg)
}
if (expansion.code == 200) {
Array.isArray(expansion.data)
&& (expansion.data = expansion.data.map(item => (item.ctype = 4, item)))
&& (myCoupons = myCoupons.concat(expansion.data))
} else {
Toast.info(expansion.msg)
}
this.setState({
couponList: myCoupons
})
})
}
getAllCoupons = () => {
http.post(`${API.home}/m/coupon/select`, {course_id: this.state.courseId})
.then(res => {
const data = res.data
if (data.code === 200) {
const inuse_coupon = data.data['inuse_coupon'];
Promise.all([
http.post(`${API.home}/m/coupon/select`, {course_id: this.state.courseId}),
http.get(`${API.home}/m/coupon/expansion`)
]).then((coupons) => {
const [selectCoupons, expansionCoupons] = coupons
const {data: select} = selectCoupons
const {data: expansion} = expansionCoupons
if (select.code === 200) {
const inuse_coupon = select.data['inuse_coupon']
this.setState({
valid_coupons: inuse_coupon
? [...inuse_coupon, ...select.data.valid_coupons]
: select.data.valid_coupons,
invalid_coupons: select.data.invalid_coupons,
selectedCouponId: inuse_coupon.length ? inuse_coupon[0].id : 0
})
} else {
Toast.info(data.msg)
}
if (expansion.code == 200) {
Array.isArray(expansion.data)
&& (expansion.data = expansion.data.map(item => (item.ctype = 4, item)))
&& (this.setState({
valid_coupons: this.state.valid_coupons.concat(expansion.data)
}))
} else {
Toast.info(expansion.msg)
}
this.setState({
valid_coupons: inuse_coupon
? [...inuse_coupon, ...data.data.valid_coupons]
: data.data.valid_coupons,
invalid_coupons: data.data.invalid_coupons,
selectedCouponId: inuse_coupon.length ? inuse_coupon[0].id : 0
})
} else {
Toast.info(data.msg)
}
})
})
}
// 立即兑换课程
toExchangeCourse = (e, code) => {
e.stopPropagation();
e.stopPropagation()
http.post(`${API['base-api']}/pay/miandan/${code}`, {}).then(res => {
const data = res.data
if (data.errno === 200) {
......@@ -163,7 +190,7 @@ class UseCoupon extends PureComponent {
}
useCoupon = val => {
const {history, dispatch} = this.props
const {history} = this.props
const coupon = this.state.couponList.find(item => item.id === val)
if (val) {
......@@ -172,8 +199,8 @@ class UseCoupon extends PureComponent {
if (coupon['limit_course'] === 0) {
history.push(`/classify`)
} else {
history.push(`/detail?id=${coupon['limit_course']}`);
return false;
history.push(`/detail?id=${coupon['limit_course']}`)
return false
}
} else {
......@@ -233,7 +260,7 @@ class UseCoupon extends PureComponent {
// 开始学习
toStudy = (vCourseId, isHaveVideo) => {
const {history} = this.props;
const {history} = this.props
if (isHaveVideo == 0) {
Toast.info('尚未开课,开课后立即上传课程~', 2)
} else {
......@@ -251,6 +278,18 @@ class UseCoupon extends PureComponent {
})
}
endExpansion = id => {
this.setState({
couponList: this.state.couponList.map(item => {
if (item.id === id) {
delete item.start_amount
}
return item
})
})
}
render() {
const {state} = this.props.location
const {showUseButton, selectedCouponId} = this.state
......@@ -273,6 +312,7 @@ class UseCoupon extends PureComponent {
select={this.select}
useCoupon={this.useCoupon}
toExchangeCourse={this.toExchangeCourse}
endExpansion={this.endExpansion}
/>
{
this.state.invalid_coupons.length > 0 &&
......@@ -296,7 +336,7 @@ class UseCoupon extends PureComponent {
courseCouponData={this.state.courseCouponData}/>
}
</div>
);
)
}
}
......@@ -351,4 +391,4 @@ function FreeCouponCourse(props) {
)
}
export default WithFullSize(UseCoupon);
\ No newline at end of file
export default WithFullSize(UseCoupon)
......@@ -243,6 +243,41 @@ class BtnStatus extends Component {
})
}
// 付定金 付尾款
expandPay = (info,type)=>{
// type 等于1是定金 等于2是尾款
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
if(type == 1){
this.props.history.push(
`/deposit-order?oid=${getParam('id')}&source=${1}`,
{
id: getParam('id'),
isexpand: 1,
sourcenum: 1
}
)
} else {
let timeStamp = Date.parse(new Date()) / 1000;
if (timeStamp >= info.start_timestamp) {
this.props.history.push(
'/final-deposit-order?source=1',
{
id: getParam('id'),
sourcenum: 1
}
)
} else {
Toast.info("付尾款时间将在" + info.final_start_time + "开启",2);
}
}
}
}
render() {
// data 课程信息;barInfo 砍价信息
const { user = {}, toCart } = this.props;
......@@ -271,6 +306,22 @@ class BtnStatus extends Component {
</div>
}
{/* 定金课程 is_deposit 是否定金课程 0-否 1-付定金 2-付尾款*/}
{
info.is_baoming === 0 && info.is_deposit != 0 &&
<div className='btns-box'>
<a className='consult consult-m' href="https://q.url.cn/AB8aue?_type=wpa&qidian=true">
<i className='iconfont iconerji' />
<span>课程咨询</span>
</a>
<div className='btn btn-m bg-FD7700' onClick={()=>this.expandPay(info.deposit_info,info.is_deposit)}>
{info.is_deposit == 1 ? '立即付定金':'立即付尾款'}
</div>
</div>
}
{/*已购买*/}
{
info.is_baoming === 1 &&
......
import React, {Component} from 'react'
import './index.scss'
import {connect} from "react-redux"
import {withRouter} from 'react-router-dom'
import {compose} from "redux"
class Deposit extends Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
const {courseInfo} = this.props;
let info = ''
if (courseInfo) {
info = courseInfo.deposit_info
}
return (
<div className="buy-expand">
<p className="buy-time">付定金时间:{info.deposit_start_time}-{info.deposit_end_time}</p>
<p className="buy-time">付尾款时间:{info.final_start_time}-{info.final_end_time}</p>
<div className="expand-bgimg">
<img
className="four-year"
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/4year.png"
alt=''
/>
<span className="dingjin">定金{info.deposit_amount}元,可抵扣{info.deduction_amount}</span>
<p className="small">
到手价最低:¥
<span>{info.low_price}</span>
</p>
<p className="else-tip">另可获得最高{info.deposit_coupon}元代金券进行叠加</p>
</div>
</div>
);
}
}
export default compose(
connect(
state => ({
user: state.user
}),
null
),
withRouter
)(Deposit)
.buy-expand {
margin-top: 5px;
.buy-time {
color: #999;
font-size: 12px;
text-align: left;
padding-left: 15px;
margin-bottom: 8px;
}
.expand-bgimg {
position: relative;
width: 100%;
height: 70px;
background-size: cover;
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/detail-expand-bg.png");
.four-year {
width: 104px;
height: 32px;
position: absolute;
left: 12px;
top: 7px;
}
.dingjin {
color: #f5f5f5;
font-size: 15px;
position: absolute;
right: 12px;
top: 20px;
}
.small {
color: #f5f5f5;
font-size: 14px;
position: absolute;
left: 12px;
bottom: 6px;
span {
font-size: 18px;
}
}
.else-tip {
color: #f5f5f5;
font-size: 12px;
position: absolute;
right: 12px;
bottom: 10px;
}
}
}
......@@ -10,6 +10,7 @@ import Single from "./single"
import SingleSuccess from './single/singleSuccess';
import BtnStatus from "./btnstatus"
import Barrage from './barrage'
import Deposit from './deposit'
import {connect} from "react-redux"
import {getCourses, addCourseToCart} from "./actions"
import {getParam, http, browser, wxShare} from "@/utils"
......@@ -19,6 +20,7 @@ import {delCountryNum} from './../country/countryRedux';
import RedPacket from './redPacket';
import {Link} from "react-router-dom";
import ExpandActiveToast from "../Index/expandActiveToast";
class Detail extends Component {
......@@ -475,6 +477,10 @@ class Detail extends Component {
cart={true}
toHref={href}
/>
<ExpandActiveToast/>
<CallApp className='toapp' path={`/detail/id=${getParam('id')}`} />
{/*弹幕*/}
......@@ -500,10 +506,13 @@ class Detail extends Component {
<span className="old">¥{course_info.price0}</span>
</p>
}
{/*{*/}
{/*course_info.is_baoming === 1 &&*/}
{/*<span className="isbuy">已购买</span>*/}
{/*}*/}
{
!!course_info.is_deposit && course_info.is_deposit!= 0 &&
<div className="openExpand">
支付定金¥{course_info.deposit_info.deposit_amount},可抵扣¥{course_info.deposit_info.deduction_amount}
</div>
}
</div>
</div>
</div>
......@@ -550,6 +559,15 @@ class Detail extends Component {
</div>
}
{/*定金相关信息*/}
{
!!course_info.is_deposit && course_info.is_deposit!= 0 &&
<Deposit courseInfo={course_info}/>
}
{/*服务承诺*/}
<div className='promise'>
<label>服务承诺</label>
......@@ -643,9 +661,9 @@ class Detail extends Component {
*/}
{
course_info.is_baoming === 0 && (!course_info.is_aist) && course_info.is_bargain &&
<Bargain
country={this.props.country}
delCountryNum={this.props.delCountryNum}
<Bargain
country={this.props.country}
delCountryNum={this.props.delCountryNum}
/>
}
......@@ -719,4 +737,4 @@ const mapDispatchToProps = (dispatch) => {
}
export default connect(mapStateToProps, mapDispatchToProps)(Detail)
\ No newline at end of file
export default connect(mapStateToProps, mapDispatchToProps)(Detail)
......@@ -222,4 +222,11 @@
}
}
}
.openExpand {
font-size: 14px;
color: #ff2121;
font-weight: 500;
width: 215px;
}
}
\ No newline at end of file
import React, {Component} from 'react'
import './callback.scss'
import {http, getParam} from '@/utils'
import {Toast} from 'antd-mobile'
import {connect} from "react-redux";
class ExpandCallback extends Component {
state = {
data: ''
}
componentDidMount() {
this.getIndexData()
}
// 获取膨胀券相关
getIndexData = () => {
http.post(`${API['base-api']}/m/deposit/coupon`, {order_id: getParam('order_id')}).then((res) => {
if (res.data.errno == 200) {
const {data} = res.data
this.setState({
data: data,
})
} else {
Toast.info(res.data.msg, 2)
}
})
}
// 邀请好友助力
invitation = (url) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
window.location.href = url
}
}
render() {
let data = this.state.data
return (
<div className="callback-box">
<div className="banner"></div>
<div className="content">
<div className="title">恭喜你,获得一张</div>
<div className="coupon">
<p className="coupon-name">膨胀券</p>
<p className="coupon-price"><span>{data.amount}</span>元</p>
<p className="coupon-time">有效期至:{data.expire_time}</p>
</div>
<div className="tip">
<ul>
{
new Array(19).fill('1').map((item, index) => {
return <li key={index}/>
})
}
</ul>
全场通用
</div>
<div className="expand">
<span className="expand-small">{data.amount}</span>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/expand.png" alt=""/>
<span className="expand-big">{data.limit_amount}</span>
</div>
<button className="invitation"
onClick={() => this.invitation(data.share_url)}>邀请好友助力,{data.amount}元变{data.limit_amount}
</button>
<div className="active-time">活动时间:{data.start_time}-{data.end_time}</div>
<div className="active-tip">送助力好友{data.limit_amount}元!</div>
</div>
</div>
)
}
}
export default connect(
state => ({
user: state.user
}),
)(ExpandCallback)
.callback-box {
width: 100%;
height: 100%;
position: relative;
.banner {
width: 100%;
height: 258px;
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/bg-img.png");
background-repeat: no-repeat;
background-size: contain;
}
.content {
position: absolute;
top: 13px;
left: 10px;
width: 355px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, .06);
padding: 18px 10px 25px 10px;
.title {
text-align: center;
color: #FF3131;
font-size: 18px;
font-weight:500;
}
.coupon {
background-color: #8361FE;
width: 335px;
height: 95px;
border-radius: 3px 3px 0 0;
margin-top: 10px;
padding: 10px 12px;
color: #fff;
p {
width: 100%;
text-align: center;
font-size: 12px;
}
.coupon-name {
text-align: left;
font-size: 14px;
height: 16px;
line-height: 16px;
}
.coupon-price {
height: 28px;
line-height: 28px;
span {
font-size: 26px;
}
}
.coupon-time {
margin-top: 3px;
}
}
.tip {
width: 335px;
height: 37px;
padding-left: 12px;
text-align: left;
font-size: 12px;
color: #666;
line-height: 37px;
background-color: #fff;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, .1);
border-radius: 0 0 3px 3px;
position: relative;
ul {
position: absolute;
top: -5px;
left: 0;
width: 100%;
display: flex;
justify-content: space-around;
li {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #fff;
}
}
}
.expand {
color: #FF3131;
margin-top: 15px;
font-size: 22px;
text-align: center;
img {
margin: 0 15px;
}
.expand-big {
font-size: 30px;
}
}
.invitation {
width: 320px;
height: 44px;
background-color: #8361FE;
border-radius: 4px;
font-size: 16px;
color: #fff;
margin-top: 15px;
border: none;
}
.active-time {
color: #999;
font-size: 14px;
margin-top: 10px;
text-align: center;
}
.active-tip {
color: #8361FE;
font-size: 16px;
margin-top: 13px;
text-align: center;
}
}
}
import React, {Component} from 'react'
import './share.scss'
import {http, getParam, browser, wxShare} from '@/utils'
import {Toast} from 'antd-mobile'
import {connect} from "react-redux";
import {Link} from "react-router-dom";
import showAlert from '@common/deposit/end-expansion-alert'
class ExpandShare extends Component {
state = {
isShow: false, //活动规则
step: 0, // 区分弹窗
data: '', //膨胀券相关
courseList: [], // 预售课程列表
isshowMore: true, // 是否显示查看更多
pageCount: 1, // 页码
helpData: '',// 帮助好友助力数据
courseListMore: '', // 所有课程
}
componentDidMount() {
this.getListorData()
this.getCourseList()
wxShare({
title: '七月在线4岁啦,80元红包等你来拿!',
desc: '重磅好课1元购,大奖、红包轰趴7天7夜',
link: window.location.href,
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/shareimg.png',
})
}
// 获取膨胀券相关
getListorData = () => {
http.get(`${API['base-api']}/sys/help_list/${getParam('deposit_code')}`).then((res) => {
const {data, errno, msg} = res.data
if (errno == 200) {
this.setState({
data: data
})
} else {
Toast.info(msg, 2)
}
})
}
// 获取课程列表
getCourseList = () => {
const _this = this
http.get(`${API['base-api']}/anniversary2019/pre_course`).then((res) => {
const {data, errno, msg} = res.data
if (errno == 200) {
if (JSON.stringify(data) == '{}') {
_this.setState({
isshowMore: false,
courseList: []
})
} else if (data.length <= 6) {
_this.setState({
isshowMore: false,
courseList: data
})
} else {
_this.setState({
isshowMore: true,
courseList: data.slice(0, 6),
courseListMore: data
})
}
} else {
Toast.info(msg, 2)
}
})
}
// 获取更多课程
getMoreCourseList = () => {
this.setState({
courseList: this.state.courseListMore,
isshowMore: false
})
}
// 立即付定金
expandPaydj = (courseId) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
this.props.history.push(
`/deposit-order?oid=${getParam('id')}&source=${1}`,
{
id: courseId,
isexpand: 1,
sourcenum: 1
}
)
}
}
// 立即付尾款
expandPaywk = (courseId, time, day) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
let timeStamp = Date.parse(new Date()) / 1000;
if (timeStamp >= time) {
this.props.history.push(
'/final-deposit-order?source=1',
{
id: courseId,
sourcenum: 1
}
)
} else {
Toast.info("付尾款时间将在" + day + "开启", 2);
}
}
}
// 去学习
tostudy = (courseId) => {
this.props.history.push(`/getDetail?id=${courseId}`)
}
// 显示活动规则
showRule = () => {
this.setState({
isShow: true,
step: 1
})
}
// 邀请好友
share = () => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
this.setState({
isShow: true,
step: 0
})
}
}
// 帮好友助力
helpFriend = (id) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
http.post(`${API['base-api']}/sys/help/${id}`).then((res) => {
const {data, errno, msg} = res.data
if (errno == 200) {
this.setState({
isShow: true,
step: 2,
helpData: data
})
console.log(data)
} else if (errno === 17018 || errno === 17020) {
this.setState({
isShow: true,
step: 4
})
} else {
Toast.info(msg, 2)
}
})
}
}
// 结束助力
isendExpand = (data) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
const {amount, limit_amount, id} = data
showAlert({
amount,
limit_amount,
onCancel: () => {
this.setState({
isShow: false
})
},
onConfirm: () => {
http.post(`${API['base-api']}/sys/end_expansion`, {
id
})
.then(res => {
const {errno, msg} = res.data
if (errno == 200) {
this.setState({
isShow: false
})
this.getListorData()
} else {
Toast.info(msg)
}
})
}
})
}
}
// 关闭弹窗
close = () => {
this.setState({
isShow: false
})
}
render() {
const {isShow, step, data, courseList, isshowMore, helpData} = this.state
return (
<div className="expand-box">
<div className="banner">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/zl-banner.png" alt=""/>
<span onClick={() => this.showRule()}/>
</div>
<div className="all-contnet">
<div className="content">
{/*进度||膨胀券*/}
{
<ExpansionStatus data={data}/>
}
{/*button*/}
{
<ButtonStatus data={data} share={this.share} helpFriend={this.helpFriend}
isendExpand={this.isendExpand}/>
}
</div>
{/*好友助力列表*/}
{
(data.oneself === 1 || data.help_list && data.help_list.length !== 0) &&
<FriendList data={data}/>
}
{/*预售课程列表*/}
{
<CourseList data={courseList}
isshowMore={isshowMore}
getMoreCourseList={this.getMoreCourseList}
expandPaydj={this.expandPaydj}
expandPaywk={this.expandPaywk}
tostudy={this.tostudy}
/>
}
</div>
{
isShow &&
<div className='mbc-box'>
{
step === 0 &&
<ShareBox close={this.close} share={this.share} data={data}/>
}
{
step === 1 &&
<ActiveRule/>
}
{
step === 2 &&
<AssistanceSuccess share={this.share} data={data} helpData={helpData}/>
}
{
step === 4 &&
<AssistanceErron close={this.close}/>
}
{
(step === 1 || step === 2) &&
<img className="close"
onClick={() => this.close()}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/Public/img/guanbi_icon.png"
alt=""/>
}
</div>
}
</div>
)
}
}
// 活动规则
function ActiveRule() {
return (
<div className='content active-rule'>
<div className="title">活动规则</div>
<p>1、本活动期间,可以助力1位好友不同课程发起的膨胀,但是只能为同一好友;</p>
<p>2、好友发起膨胀后,可以随时终止膨胀;</p>
<p>3、膨胀券膨胀完成后,以优惠券形式发放到参与活动的账号(包括所有助力好友),该膨胀券为全场通用券,可在购买任一课程后进行抵扣(包括已付定金课程);</p>
<p>4、如有疑问,可联系七月在线客服微信:julyedukefu</p>
<p>*本活动最终解释权归七月在线所有</p>
</div>
)
}
// 邀请好友 分享弹窗
function ShareBox(props) {
const {close, data} = props
return (
<div className='content'>
<div onClick={() => close()} className="fiexd"></div>
<div className="share-box">
{
browser.isWeixin &&
<img src="//julyedu-cdn.oss-cn-beijing.aliyuncs.com/share/throw_icon.png" alt=""/>
}
<p>邀请好友助力</p>
<p>膨胀券翻倍膨胀,{data.start_amount}元变{data.limit_amount}元!</p>
<span>送助力好友{data.limit_amount}</span>
</div>
</div>
)
}
//助力成功弹窗
function AssistanceSuccess(props) {
const {helpData, share, data} = props
return (
<div className='content assistance-success'>
<div className="title">助力成功</div>
<p className="add-price">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/add-money.png" alt=""/>
+{helpData.help_amount}
</p>
<p className="all-price">
<span>{helpData.sale_amount}</span>
</p>
<p className="assistance-tip">感谢你的助力,你们离{data.limit_amount}元又更近了哦!<br/>可以邀请其他小伙伴一起助力~</p>
<button onClick={() => share()}>邀请更多好友拿{data.limit_amount}</button>
</div>
)
}
// 助力失败弹窗
function AssistanceErron(props) {
const {close} = props
return (
<div className="content assistance-erron">
<div className="title">温馨提示</div>
<p>很遗憾~</p>
<p>你已经帮别的好友助过力了,</p>
<p>不能再帮这位好友助力!</p>
<button onClick={() => close()}>知道了</button>
</div>
)
}
// 判断是否结束膨胀
function ExpansionStatus(props) {
const {data} = props
//is_end: 0 判断活动是否结束 0否1是
// is_end_expansion: 0,是否是自己结束膨胀 0否1是
if (data.is_end === 0 && data.is_end_expansion === 0) {
return (
<ProgressData data={data}/>
)
} else {
return (
<EndExpansion data={data}/>
)
}
}
// 没有结束膨胀的情况
function ProgressData(props) {
const data = props.data
return (
<div>
<div className="user-mess">
<img src={data.avatar_file} alt="user"/>
帮我助力,送你{data.limit_amount}
</div>
<div className="progress-box">
<div className="progress-base">
<span className="progress-active"
style={{width: (data.amount - data.start_amount) / data.limit_amount * 100 + '%'}}>
<span className="ending">
<span className="tip">{data.amount} <i/></span>
</span>
</span>
</div>
<div className="progress-price">
<span>{data.start_amount}</span>
<span>{data.limit_amount}</span>
</div>
</div>
{
data.help_list.length === 0 &&
<div className="help-mess no">还没有好友为{data.oneself === 1 ? '你' : 'Ta'}助力哦~</div>
}
{
data.help_list.length > 0 &&
<div className="help-mess has">已有<span className="FF19A0">{data.help_list.length}</span>位好友助力</div>
}
</div>
)
}
// 结束膨胀的情况
function EndExpansion(props) {
const data = props.data
return (
<div className='coupon-box'>
<div className="coupon">
<p className="coupon-name">红包膨胀优惠券</p>
<p className="coupon-price"><span>{data.amount}</span>元</p>
<p className="coupon-time">有效期至:{data.expire_time}</p>
</div>
<div className="tip">
<ul>
{
new Array(19).fill('1').map((item, index) => {
return <li key={index}/>
})
}
</ul>
全场通用
</div>
<p className="over-mess">该礼券已成功发放至账户</p>
<p className="over-mess">可在七月在线pc/app-我的-优惠券查看</p>
</div>
)
}
// 按钮
function ButtonStatus(props) {
const {data, share, helpFriend, isendExpand} = props
// data.oneself 判断是否是自己 0帮好友助力 1自己
// data.is_help 是否已经帮好友助力 0 未助力 1已助力
// data.s_end: 0 判断活动是否结束 0否1是
// data.is_end_expansion: 0,是否是自己结束膨胀 0否1是
return (
<div>
{
data.is_end === 0 &&
<div className='btns'>
{
data.oneself === 1 && data.is_end_expansion === 0 &&
<button className="active" onClick={() => share()}>邀请好友助力</button>
}
{
data.oneself === 1 && data.is_end_expansion === 1 && data.amount !== data.limit_amount &&
<button className="over">您已结束膨胀</button>
}
{
data.oneself === 1 && data.is_end_expansion === 1 && data.amount === data.limit_amount &&
<button className="over">达到膨胀上限,快去使用吧</button>
}
{
data.oneself === 0 && data.is_help === 0 && data.is_end_expansion === 0 &&
<button className="active" onClick={() => helpFriend(data.id)}>ta助力</button>
}
{
data.oneself === 0 && data.is_help === 1 && data.is_end_expansion === 0 &&
<button className="active" onClick={() => share()}>邀请更多好友拿{data.limit_amount}</button>
}
{
data.oneself === 0 && data.is_end_expansion === 1 && data.amount === data.limit_amount &&
<button className="over">达到膨胀上限,快去使用吧</button>
}
{
data.oneself === 0 && data.is_end_expansion === 1 && data.amount !== data.limit_amount &&
<button className="over">你的好友已结束助力</button>
}
</div>
}
{
data.is_end === 1 &&
<div className="btns">
<button className="over">活动已结束</button>
</div>
}
{
data.is_end === 0 && data.is_end_expansion === 0 && data.oneself === 1 &&
<div className="overBtn">
<p onClick={() => isendExpand(data)}>结束助力使用礼券</p>
</div>
}
</div>
)
}
// 好友助力列表
function FriendList(props) {
const data = props.data
return (
<div className="friend-list">
<p className="title">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/expand-right.png" alt=""/>
<span>好友助力</span>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/expand-left.png" alt=""/>
</p>
{
data.help_list.length === 0 &&
<div className="null-list">
<p className="tips first-tips">还没有好友为你助力,</p>
<p className="tips">赶紧去邀请好友吧!</p>
</div>
}
{
data.help_list.length > 0 &&
<div className="all-list">
<p className="friend-status"><span className="FF19A0">{data.help_list.length}</span>位好友共助力<span
className="FF19A0">{data.amount - data.start_amount}</span>元</p>
<ul className="all-list-box">
{
data.help_list.map((item, index) => {
return (
<li className="item" key={index}>
<img className="avait" src={item.avatar} alt=""/>
<span className="time">助力时间:{item.add_time}</span>
<span className="zlprice FF19A0">{item.amount}</span>
</li>
)
})
}
</ul>
</div>
}
</div>
)
}
//预售课程
function CourseList(props) {
const {data, isshowMore, getMoreCourseList, expandPaydj, expandPaywk, tostudy} = props
return (
<div className="advance-sale-course">
<p className="title">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/expand-right.png" alt=""/>
<span>预售课程</span>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/expand-left.png" alt=""/>
</p>
<div className="course-list">
<ul>
{
data.map((item, index) => {
return (
<li className="course-item" key={index}>
<Link to={`/getDetail?id=${item.course_id}`}>
<img className="course-img" src={item.image_name} alt=""/>
</Link>
<p className="old-price">原价:<span>¥{item.price}</span></p>
<p className="handsel">定金¥{item.deposit_amount},可抵扣¥{item.deduction_amount}</p>
<div className="btn">
{
item.is_buy === 0 &&
<a className="to-expand-buy1"
onClick={() => expandPaydj(item.course_id)}>立即付定金</a>
}
{
item.is_buy === 1 &&
<a className="to-expand-buy2"
onClick={() => expandPaywk(item.course_id, item.start_timestamp, item.final_start_time)}>立即付尾款</a>
}
{
item.is_buy === 2 &&
<button className="to-study"
onClick={() => tostudy(item.course_id)}>开始学习</button>
}
</div>
</li>
)
})
}
</ul>
</div>
{
isshowMore &&
<div className="more">
<div onClick={() => getMoreCourseList()}>
查看更多
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/expand-btm.png"
alt=""/>
</div>
</div>
}
</div>
)
}
export default connect(
state => ({
user: state.user
}),
)(ExpandShare)
.expand-box {
width: 100%;
height: 100%;
position: relative;
.FF19A0{
color: #FF19A0;
}
.banner {
width: 100%;
height: 323px;
position: relative;
z-index: 1;
span {
position: absolute;
top: 48px;
right: 22px;
width: 30px;
height: 83px;
}
}
.all-contnet {
position: absolute;
top: 180px;
width: 100%;
background-color: #f5f5f5;
.content {
position: relative;
z-index: 2;
background-color: #fff;
width: 355px;
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, .06);
padding: 17px 19px;
border-radius: 8px 8px 4px 4px;
margin-left: 10px;
.user-mess {
text-align: left;
color: #111;
font-size: 14px;
img {
width: 24px;
height: 24px;
border-radius: 50%;
vertical-align: middle;
margin-right: 9px;
}
}
.progress-box {
margin-top: 50px;
.progress-base {
width: 318px;
height: 8px;
line-height: 8px;
background-color: #DCDCDC;
border-radius: 4px;
text-align: left;
.progress-active {
display: inline-block;
height: 100%;
border-radius: 4px;
background-color: #FF19A0;
padding-left: 10px;
position: relative;
.ending {
display: inline-block;
width: 14px;
height: 14px;
border-radius: 50%;
background-color: #fff;
position: absolute;
right: 0;
top: -3px;
border: 3px solid #FF19A0;
.tip {
display: inline-block;
width: 55px;
height: 20px;
line-height: 21px;
background-color: #FF19A0;
border-radius: 3px;
position: absolute;
top: -30px;
left: -23px;
text-align: center;
color: #fff;
i {
display: inline-block;
width: 6px;
height: 6px;
background-color: #FF19A0;
transform: rotate(45deg);
position: absolute;
bottom: -3px;
left: 50%;
margin-left: -3px;
}
}
}
}
}
.progress-price {
width: 100%;
display: flex;
justify-content: space-between;
color: #FF19A0;
font-size: 14px;
margin-top: 3px;
}
}
.help-mess {
font-size: 15px;
margin-top: 10px;
text-align: center;
}
.no {
color: #666;
}
.has {
color: #000011;
}
.coupon-box {
.coupon {
background-color: #8361FE;
width: 316px;
height: 85px;
border-radius: 3px 3px 0 0;
padding: 10px 12px;
color: #fff;
p {
width: 100%;
text-align: center;
font-size: 12px;
}
.coupon-name {
text-align: left;
font-size: 14px;
height: 16px;
line-height: 16px;
}
.coupon-price {
height: 28px;
line-height: 28px;
span {
font-size: 26px;
}
}
}
.tip {
width: 316px;
height: 33px;
padding-left: 12px;
text-align: left;
font-size: 12px;
color: #666;
line-height: 33px;
background-color: #fff;
box-shadow: 0 6px 12px 0 rgba(131, 97, 254, 0.1);
border-radius: 0 0 3px 3px;
position: relative;
margin-bottom: 16px;
ul {
position: absolute;
top: -5px;
left: 0;
width: 100%;
display: flex;
justify-content: space-around;
li {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #fff;
}
}
}
.over-mess {
text-align: center;
font-size: 12px;
color: #333;
}
}
.btns {
button {
width: 318px;
height: 44px;
border-radius: 22px;
box-shadow: 0 6px 12px 0 rgba(131, 97, 254, 0.1);
color: #fff;
font-size: 16px;
border: none;
}
.active {
margin-top: 25px;
background-color: #8361FE;
}
.over {
margin-top: 15px;
background-color: #CCCCCC;
}
}
.overBtn {
width: 100%;
margin-top: 15px;
font-size: 14px;
color: #666;
text-decoration: underline;
text-align: center;
}
}
.friend-list {
width: 100%;
margin-top: 12px;
padding: 17px 28px 24px 28px;
background-color: #fff;
.title {
font-size: 18px;
color: #111;
font-weight: 500;
text-align: center;
margin: 0 5px;
img {
width: 59px;
height: 11px;
vertical-align: middle;
}
span {
margin: 0 10px;
}
}
.null-list {
text-align: center;
margin-bottom: 20px;
.tips {
font-size: 15px;
color: #999;
margin-top: 5px;
}
.first-tips {
margin-top: 35px;
}
}
.all-list {
margin-top: 10px;
.friend-status {
font-size: 14px;
color: #333;
text-align: center;
}
.all-list-box {
margin-top: 7px;
width: 100%;
.item {
margin-top: 15px;
height: 24px;
line-height: 24px;
text-align: left;
font-size: 14px;
.avait {
width: 24px;
height: 24px;
border-radius: 50%;
vertical-align: middle;
}
.time {
margin-left: 26px;
}
.zlprice {
float: right;
}
}
}
}
}
.advance-sale-course {
width: 100%;
margin-top: 12px;
background-color: #fff;
padding: 15px 10px 20px 10px;
.title {
text-align: center;
font-size: 18px;
color: #111;
font-weight: 500;
img {
width: 59px;
height: 11px;
vertical-align: middle;
}
span {
margin: 0 10px;
}
}
.course-list {
margin-top: 15px;
ul {
display: flex;
justify-content: space-between;
flex-direction: row;
flex-wrap: wrap;
.course-item {
width: 48.4%;
background-color: #fff;
padding-bottom: 14px;
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, .06);
border-radius: 2px;
margin-bottom: 10px;
text-align: left;
margin-top: 0;
.course-img {
width: 100%;
height: 124px;
border-radius: 2px;
}
.old-price {
margin-top: 8px;
font-size: 12px;
color: #999;
padding-left: 10px;
span {
font-size: 15px;
color: #FF3131;
}
}
.handsel {
margin-top: 5px;
font-size: 12px;
color: #666;
padding-left: 10px;
}
.btn {
width: 100%;
padding: 0 10px;
margin-top: 12px;
button {
width: 100%;
height: 27px;
border-radius: 2px;
font-size: 12px;
color: #fff;
border: none;
}
.to-expand-buy1, .to-expand-buy2 {
display: inline-block;
width: 100%;
text-align: center;
height: 27px;
line-height: 27px;
border-radius: 2px;
font-size: 12px;
color: #fff;
}
.to-expand-buy1 {
background-color: #8361FE;
}
.to-expand-buy2 {
background-color: #FF4000;
}
.to-study {
background-color: #0099FF;
}
}
}
}
}
.more {
font-size: 14px;
color: #666;
height: 56px;
line-height: 56px;
text-align: center;
div {
width: 130px;
margin: auto;
}
img {
width: 13px;
height: 12px;
margin-left: 8px;
margin-top: -3px;
vertical-align: middle;
}
}
}
}
.mbc-box {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .6);
z-index: 3;
.content {
border-radius: 8px;
background-color: #fff;
margin: 0 auto 24px auto;
width: 300px;
.title {
text-align: center;
font-size: 21px;
color: #333;
font-weight: 600;
}
}
.active-rule {
margin-top: 122px;
padding: 20px;
p {
text-align: left;
font-size: 14px;
color: #666;
margin-top: 15px;
}
}
.fiexd {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
}
.share-box {
padding: 17px 0 20px 0;
margin-top: 100px;
text-align: center;
position: relative;
img {
position: absolute;
width: 60px;
height: 44px;
right: 0;
top: -48px;
}
p {
color: #333;
font-size: 15px;
margin-bottom: 10px;
height: 17px;
line-height: 17px;
}
span {
display: inline-block;
color: #999;
font-size: 12px;
margin-top: 10px;
height: 14px;
line-height: 14px;
}
}
.assistance-success {
margin-top: 197px;
text-align: center;
padding: 20px 0;
.add-price {
margin-top: 10px;
color: #FF3131;
font-size: 12px;
img {
width:8px;
height: 12px;
vertical-align: text-top;
}
}
.all-price {
margin-top: 10px;
color: #FF3131;
font-size: 12px;
span {
font-size: 30px;
}
}
.assistance-tip {
margin-top: 10px;
color: #999;
font-size: 14px;
}
button {
width: 225px;
height:36px;
background-color: #8361FE;
box-shadow: 0 6px 12px 0 rgba(131, 97, 254, .1);
border-radius: 18px;
color: #fff;
font-size: 15px;
margin-top: 20px;
}
}
.assistance-erron {
margin-top: 220px;
text-align: center;
padding: 20px 0;
.title {
margin-bottom: 15px;
}
p {
color: #666;
font-size: 14px;
margin-top: 8px;
}
button {
margin-top: 15px;
width: 146px;
height: 33px;
background-color: #8361FE;
border-radius: 17px;
color: #fff;
font-size: 15px;
}
}
.close {
width: 30px;
height: 30px;
position: absolute;
left: 50%;
margin-left: -15px;
}
}
}
\ No newline at end of file
......@@ -16,6 +16,7 @@ const alert = Modal.alert
@connect()
class MyOrders extends Component {
page = 1
constructor(props) {
super(props)
this.state = {
......@@ -31,7 +32,7 @@ class MyOrders extends Component {
}
getMore = debounce(() => {
if(this.state.data.length % 10 === 0){
if (this.state.data.length % 10 === 0) {
this.getList(++this.page)
}
}, 200)
......@@ -74,10 +75,10 @@ class MyOrders extends Component {
}
toCourseDetail = (id) => {
const { dispatch, history } = this.props;
const {dispatch, history} = this.props;
// dispatch(getCourses(id, () => {
history.push(`/detail?id=${id}`);
return false;
history.push(`/detail?id=${id}`);
return false;
// }));
}
......@@ -88,7 +89,7 @@ class MyOrders extends Component {
<HeaderBar title='我的订单' arrow={true} cart={false}></HeaderBar>
<Loading isLoading={this.state.isLoading}>
{
this.state.data && JSON.stringify(this.state.data) !== '[{}]'?
this.state.data && JSON.stringify(this.state.data) !== '[{}]' ?
<InfiniteScroll
pageStart={0}
hasMore={true}
......@@ -104,10 +105,9 @@ class MyOrders extends Component {
item.course && item.course.length > 0 && item.course.map((item, index) => {
const Info = (
<div className="order-info">
<p className='order-title text-overflow-one' onClick={() => this.toCourseDetail(item.course_id)}>
{/* <Link to={`/detail?id=${item.course_id}`}> */}
{item.course_title}
{/* </Link> */}
<p className='order-title text-overflow-one'
onClick={() => this.toCourseDetail(item.course_id)}>
{item.course_title}
</p>
<p className='order-content text-overflow-2'>{item.description}</p>
<p className='order-des'>
......@@ -133,6 +133,14 @@ class MyOrders extends Component {
}
<PayInfo item={item} cancel={this.cancel}/>
{
item.type == 5 && item.is_buy == 0 &&
<div className={'expand-pay-wk'}>
<span className={'expand-pay-time'}>{item.final_end_time}结束付尾款</span>
<span>还需支付尾款</span>
</div>
}
</div>
)
})
......@@ -167,11 +175,20 @@ function OrderInfo(props) {
}
function PayInfo(props) {
// type 0普通订单 1团购 2小团 3砍价 4单集购买 5定金课定金 6定金课尾款
let type = ''
if (props.item.type == 5) {
type = '(定金)'
}
if (props.item.type == 6) {
type = '(尾款)'
}
return (
<div className='order-btm'>
<div className='price-info'>
<p>
<span className='payable'>应付:</span>
<span className='payable'>应付{type}</span>
<span className='price'>¥{props.item.pay_amount}</span>
</p>
<p>
......
......@@ -25,7 +25,8 @@
font-size: 14px;
color: $redprice;
}
.oid-success{
.oid-success {
font-size: 14px;
color: $color_333;
}
......@@ -37,8 +38,9 @@
background-color: $bg_fff;
border-bottom: 1px solid $border_e7eaf1;
}
.order-info {
.order-des{
.order-des {
position: absolute;
bottom: 0;
}
......@@ -53,7 +55,7 @@
justify-content: space-between;
.price-info {
width: 120px;
width: 150px;
display: flex;
flex-direction: column;
align-self: center;
......@@ -105,6 +107,26 @@
}
}
}
.expand-pay-wk {
height: 35px;
background-color: $bg_fff;
line-height: 35px;
padding: 0 10px;
font-size: 12px;
display: flex;
justify-content: space-between;
border-top: 1px solid #E7EAF1;
span {
color: #999;
}
.expand-pay-time {
color: #09f;
}
}
}
.cart-tip {
......
import React, { Component } from 'react'
import { Flex, List, Toast } from 'antd-mobile'
import { OrderItem } from '@common/index'
import { Link } from 'react-router-dom'
import { http, getParam } from "@/utils"
import { HeaderBar } from '@common/index'
import "./index.scss"
const Item = List.Item
function OrderList(props) {
const listData = props.list
return (
<div>
{
listData.map((item, index) => {
const {is_coupon, course_id, image_name, sale_price, simpledescription, course_title, coupon_num, coupon_desc} = item
let NewPrice = (<span className='order-newprice'>¥{sale_price}</span>)
if (props.locationState && props.locationState.group) {
NewPrice = (<span className='order-newprice'>¥{props.groupPrice}</span>)
}
const Info = (
<div className="order-info">
<p
className='order-title'
style={{
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}}
onClick={() => props.toDetail(course_id)}
>
{course_title}
</p>
<p className='order-content' style={{
WebkitBoxOrient: 'vertical',
WebkitLineClamp: '2',
wordBreak: 'break-all',
overflow: 'hidden',
textOverflow: 'ellipsis',
display: '-webkit-box'
}}>{simpledescription}</p>
<p className='order-des'>
{NewPrice}
<span className={'price-des'}>(预付定金)</span>
</p>
</div>
)
return (
<OrderItem
{...item}
src={image_name}
id={course_id}
key={index}
info={Info}
isaist={props.isaist}
toDetail={props.toDetail}
>
{
(props.locationState && (props.locationState.type || props.locationState.simple)) ? (
<div className="order-prefer">
<List key={index}>
<Item
arrow="horizontal"
onClick={() => {
}}
>
<Link to={{
pathname: `/coupons`,
search: `?id=${course_id}`,
state: {
from: '/order'
}
}}>
<Flex justify='between'>
<span
style={{
color: '#333',
fontSize: '15px'
}}
>优惠券</span>
<span
style={{
fontSize: '14px',
color: '#999999'
}}
>
{!coupon_desc ? (coupon_num === 0 ? '无' : `${coupon_num}张可用`) : (coupon_desc)}
</span>
</Flex>
</Link>
</Item>
</List>
</div>
) : null
}
</OrderItem>
)
})
}
</div>
)
}
class Order extends Component {
constructor(props) {
super(props)
this.state = {
groupPrice: '',
total: 0.00, // 需要支付总金额
discount: 0.00, //
useBalance: false,
orderList: [],
info: false,
offset: 0,
depositPrice: 0,
course_id: getParam('oid'),
user_account: '',
finalStartTime: '',
}
}
// 提交订单
submitOrder = () => {
http.post(`${API["base-api"]}/m/deposit/create`, {
plat_form: 5,
source: getParam('source'), //来源 1-详情页 2-活动页,
course_id: this.state.course_id,
is_deduction: this.state.useBalance ? 1 : 0
}).then(res => {
const {data} = res
if (data.errno == 200) {
if (data.data['pay_jump']) {
this.props.history.replace(`/expand/callback?order_id=${data.data['order_id']}`)
} else {
this.props.history.replace({
pathname: '/deposit-pay-order',
search: `?oid=${data.data['order_id']}`
})
}
} else {
Toast.info(data.msg)
}
})
}
showInfo = () => {
this.setState((prevState) => ({
info: !prevState.info
}))
}
componentDidMount() {
http.post(`${API["base-api"]}/m/deposit/preorder`, {
course_id: this.state.course_id
})
.then(res => {
const {data} = res
if (data.errno == 200) {
this.setState({
orderList: [data.data.course],
depositPrice: data.data.course['sale_price'],
user_account: data.data['user_account'],
finalStartTime: data.data['final_start_time']
})
} else {
Toast.info(data.msg)
}
})
};
toCourseDetail = (id) => {
const {history} = this.props
history.push(`/detail?id=${id}`)
}
useBalance = () => {
let {user_account, depositPrice} = this.state
let offset = parseFloat(user_account) - parseFloat(depositPrice)
offset = offset > 0 ? depositPrice : user_account
this.setState(prevState => ({useBalance: !prevState.useBalance, offset}))
}
updateUserAccount = () => {
}
render() {
const {
orderList,
discount,
groupPrice,
depositPrice,
user_account,
useBalance,
info,
offset,
finalStartTime
} = this.state
return (
<div className="order-wrapper">
<Flex>
<Flex.Item>
<HeaderBar title='课程报名' arrow={true}/>
<div className="order-list">
<OrderList
list={orderList}
courseId={getParam('id')}
locationState={this.props.location.state}
groupPrice={groupPrice}
toDetail={this.toCourseDetail}
/>
</div>
<div className="order-balance">
<List>
<Item
className="order-prefer-text"
>
<Flex justify='between'>
<Flex align='center'>
<span>余额抵扣</span>
<span className="order-balanceprice"> (余额: <i
className="order-money">{`${user_account}元`}</i>)</span>
<i className="iconfont iconiconfront-22 question-mark"
onClick={this.showInfo}></i>
</Flex>
<Flex>
{
useBalance ? (
<>
<span style={{
color: '#FF2121',
fontSize: '15px',
marginRight: "6px"
}}>{`-¥${offset}`}</span>
<i className={`iconfont icondanseshixintubiao-5 balance-used`}
onClick={this.useBalance}></i>
</>
) : (
<i className='circle-icon' onClick={this.useBalance}></i>
)
}
</Flex>
</Flex>
</Item>
</List>
</div>
<ul className={'deposit-limit-time'}>
<li>· {finalStartTime}开始支付尾款</li>
<li>· 代金券只能在支付尾款时使用</li>
</ul>
<div className="order-bar">
<div className="order-course">
<span className="order-course-text">{`${orderList.length}门课程`}</span>
</div>
<div className="order-bar-text">
<div className="order-amount">
<span className="order-amount-title">合计:</span>
<span className="order-amount-price">{`¥${depositPrice}`}</span>
</div>
<div className="order-preprice">
<span className="order-preprice-title">已优惠:</span>
<span className="order-preprice-price">{${discount}`}</span>
</div>
</div>
<button type="button" className="order-button has-info">
<span className="order-button-text" onClick={this.submitOrder}>确定订单</span>
</button>
</div>
</Flex.Item>
</Flex>
{
info ? (
<div style={{
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
zIndex: '99'
}}>
<div style={{
padding: '20px',
backgroundColor: '#FFF',
width: '300px',
height: '170px',
margin: '0 auto',
position: 'absolute',
left: '50%',
top: '50%',
transform: 'translate(-50%, -50%)'
}}>
<Flex direction='column' justify='between' align='center' style={{height: '100%'}}>
<p style={{fontSize: '16px', color: '#333333'}}>余额抵扣说明</p>
<p style={{
lineHeight: '20px',
fontSize: '13px',
color: '#666666'
}}>分销课程或者参与七月在线的相关活动,可获得资金奖励。账户资金可直接提现,也可抵扣课程费用。</p>
<div onClick={this.showInfo} style={{
width: '260px',
height: '30px',
lineHeight: '30px',
textAlign: 'center',
borderRadius: '3px',
border: '1px solid #0099FF',
color: '#0099FF',
fontSize: '15px'
}}>知道了
</div>
</Flex>
</div>
</div>
) : null
}
</div>
)
}
}
export default Order
.order-wrapper {
width: 100%;
height: 100vh;
margin-bottom: 50px;
background-color: $bg_f5f5f5;
.order-tab {
color: $black;
background: $bg_f7f9fc;
}
.order-information {
display: flex;
width: 100%;
overflow: hidden;
padding: 29px 15px;
color: $color_555;
background-color: $bg_fff;
position: relative;
}
.order-information::before {
content: '';
left: 0;
right: 0;
bottom: 0;
height: 2px;
position: absolute;
background: -webkit-repeating-linear-gradient(135deg, #ff6c6c 0, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
background: repeating-linear-gradient(-45deg, #ff6c6c 0, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
background-size: 80px;
}
.order-information2 {
height: 80px;
background-color: #FFF;
margin-top: 8px;
position: relative;
.user-icon {
font-size: 28px;
flex-basis: 40px;
}
.order-cell {
height: 50px;
font-size: 13px;
color: $color_333;
line-height: 20px;
flex: 1 1 auto;
.name {
margin-bottom: 10px;
}
}
}
.order-information2::before {
content: '';
left: 0;
right: 0;
bottom: 0;
height: 2px;
position: absolute;
background: -webkit-repeating-linear-gradient(135deg, #ff6c6c 0, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
background: repeating-linear-gradient(-45deg, #ff6c6c 0, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
background-size: 80px;
}
.order-addsize {
font-size: 22px !important;
margin-bottom: 0px;
height: 22px;
color: $active;
line-height: 22px;
}
.order-next {
line-height: 22px;
margin-bottom: 0px;
}
.order-list {
margin-top: 8px;
background-color: #F5F5F5;
.public-content {
padding: 10px 15px;
}
}
.order-infotext {
flex: 1;
height: 22px;
line-height: 22px;
margin-left: 10px;
font-size: $font_14;
color: $color_555;
}
.order-info {
color: $color_666;
font-size: $font_14;
min-width: 160px;
flex: 1 1 auto;
display: flex;
flex-direction: column;
justify-content: space-around;
.order-title {
color: $color_333;
font-size: $font_16;
}
.order-content {
color: $color_666;
font-size: $font_14;
line-height: 18px;
}
.order-newprice {
color: $redprice;
font-size: $font_16;
margin-right: 8px;
}
.price-des{
color: #999;
font-size: 11px;
}
}
.order-bar {
width: 100%;
position: fixed;
bottom: 0;
z-index: 2;
height: 50px;
display: flex;
font-size: 14px;
align-items: center;
background-color: $bg_fff;
}
.order-course {
margin-left: 20px;
.order-course-text {
font-size: $font_16;
color: $color_333;
}
}
.order-bar-text {
flex: 1;
text-align: right;
color: #323233;
padding-right: 20px;
.order-amount {
font-size: $font_14;
color: $color_333;
.order-amount-price {
color: $redprice;
}
}
.order-preprice {
font-size: $font_12;
color: $color_555;
}
}
.order-button {
width: 110px;
height: 50px;
display: inline-block;
padding: 0;
background-color: $bg_ff9898;
color: $white;
line-height: 48px;
font-size: 16px;
border-radius: 0px;
text-align: center;
box-sizing: border-box;
-webkit-appearance: none;
-webkit-text-size-adjust: 100%;
border: 1px solid transparent;
}
.has-info {
background-color: #FF3131;
}
.v-list-item {
margin-top: 8px;
padding: 10px 15px 0 15px;
.content {
border-bottom: none;
}
}
.order-prefer {
.am-list-body{
&::after{
display: none;
}
}
.am-list-content {
font-size: 15px !important;
}
.am-list-line {
padding: 0 15px;
}
}
.am-list-item .am-list-line .am-list-content {
color: $color_333;
}
.order-list {
.am-list-item {
padding-left: 0 !important;
}
}
.deposit-limit-time{
background: #fff;
padding: 11px 15px;
border-top: 1px solid #E5E5E5;
border-bottom: 1px solid #E5E5E5;
font-size: 13px;
color: #666;
line-height: 1.7;
}
.order-balance {
line-height: 44px;
background: #fff;
margin: 8px 0;
.am-list-item {
padding-left: 0 !important;
}
.am-list-line {
padding: 0 15px;
}
.am-list-content {
color: $color_333;
font-size: $font_16;
.iconiconfront-22 {
font-size: 18px;
margin-left: 15px;
}
}
.order-balanceprice {
color: $color_666;
font-size: $font_12;
.order-money {
color: #ff2121;
font-size: $font_12 !important;
font-weight: normal;
font-style: inherit;
vertical-align: middle;
margin: 0;
}
}
.iconiconfront-22.question-mark {
font-size: 24px;
margin-left: 15px;
}
.am-list-body {
&::before, &::after {
display: none;
}
}
.balance-used {
font-size: 24px;
color: #0099FF;
}
.circle-icon {
width: 20px;
height: 20px;
border: 1px solid #BFBFBF;
border-radius: 50%;
margin-right: 2px;
}
}
}
import React, { Component } from 'react'
import { Flex, WingBlank, WhiteSpace, List, Radio, Toast, Checkbox } from 'antd-mobile'
import { http, getParam, is_weixin, browser } from '@/utils'
import { OrderItem, HeaderBar } from '@common/index'
import { Link } from 'react-router-dom'
import './index.scss'
import { VList } from '@/common'
import { WithFullSize } from '@/HOCs'
import classnames from 'classnames'
const RadioItem = Radio.RadioItem
let mockData = []
if (browser.isWeixin) {
mockData = [
{value: 1, label: '微信支付', icon: 'iconweixinzhifu'}
]
} else {
mockData = [
{value: 1, label: '微信支付', icon: 'iconweixinzhifu'},
{value: 0, label: '支付宝', icon: 'iconalipay'},
]
}
class PayOrder extends Component {
constructor(props) {
super(props)
this.state = {
pay_amount: 0,
payType: 1,
stageNumber: 0,
checkPeriod: false,
singleMoney: 0,
periodNumber: 0,
orderId: getParam('oid'),
huabei: false,
fenqiList: [
{value: 'zhifubao', qishu: '3', lilv: '2.30%', everyMoney: 300, feiyong: 2.3},
{value: 'weixin', qishu: '6', lilv: '4.50%', everyMoney: 150, feiyong: 4.5},
{value: 'huabei', qishu: '9', lilv: '7.50%', everyMoney: 100, feiyong: 7.5},
],
categoryList: [],
agree: false
}
}
onChange = (value) => {
this.setState({
payType: value,
checkPeriod: false,
})
if (value === 2) {
this.setState({
huabei: true,
})
}
}
// 确定购买
pay = () => {
const {payType, orderId} = this.state
if(!this.state.agree){
return
}
if (payType === 0) {
this.alipayPay(orderId)
} else if (payType === 1) {
this.weixinPay(orderId)
}
}
// 微信支付
weixinPay = (orderId) => {
// 微信内部-支付
if (is_weixin()) {
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(window.location.href + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
} else {
// 微信外部-支付
http.get(`${API['base-api']}/pay/wxpay/wap_charge/oid/${orderId}`).then((res) => {
if (res.data.errno === 0) {
window.location.href = res.data.data.url + "&redirect_url=" + encodeURIComponent(window.location.href + "&weixinpay=1").toLowerCase()
} else {
Toast.info(res.data.msg, 2)
}
})
}
}
// 微信内部支付
isweixinPay = () => {
let _this = this
let weixin_code = getParam('code')
if (weixin_code) {
if (getParam('oid') === undefined) {
return
} else {
http.get(`${API['base-api']}/pay/wxpay/pub_charge/oid/${getParam('oid')}/code/${weixin_code}`).then((res) => {
if (res.data.errno === 0) {
let data = res.data.data
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
appId: data.appId, //公众号名称,由商户传入
timeStamp: data.timeStamp, //时间戳,自1970年以来的秒数
nonceStr: data.nonceStr, //随机串
package: data.package,
signType: data.signType, //微信签名方式:
paySign: data.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
Toast.info('支付成功', 2)
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus)
_this.intervalPayStatus = null
_this.props.history.replace(`/expand/callback?order_id=${getParam('oid')}`)
}
})
}, 1000)
} else {
alert('支付失败')
}
}
)
}
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false)
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady)
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady)
}
} else {
onBridgeReady()
}
} else {
Toast.info(res.data.msg, 2)
}
})
}
}
}
// 支付完成之后获取状态
payCallback = () => {
const _this = this
// 支付回调
// 定时器轮训获取订单状态
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus)
_this.intervalPayStatus = null
window.location.href = '/expand/callback?order_id=' + getParam('oid')
}
})
}, 1000)
}
onBridgeReady1 = (data) => {
let _this = this
data = data || _this.BridgeData
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": "wx23dac6775ac82877", //公众号名称,由商户传入
"timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr": data.nonceStr, //随机串
"package": data.package,
"signType": data.signType, //微信签名方式:
"paySign": data.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
Toast.info('支付成功', 2)
_this.payCallback()
} else {
alert('支付失败')
}
}
)
}
// 支付宝支付
alipayPay = (orderId) => {
http.get(`${API['base-api']}/pay/alipay/wap_charge_new/oid/${orderId}`).then((res) => {
if (res.data.errno === 0) {
this.payCallback()
window.location = res.data.data.url
} else {
Toast.info(res.data.msg, 2)
}
})
}
componentDidMount() {
if (getParam('weixinpay')) {
this.payCallback()
}
if (browser.isWeixin) {
this.isweixinPay(getParam('oid'))
}
http.post(`${API["base-api"]}/m/deposit/detail`, {
order_id: this.state.orderId
}).then(res => {
const {data} = res
if (data.errno == 200) {
this.setState({
categoryList: [data.data.course_info],
salePrice: data.data.course_info.sale_price
})
} else {
Toast.info(data.msg)
}
})
}
changeAgreement = () => {
this.setState((prevState) => ({agree: !prevState.agree}))
}
render() {
const {
orderId,
salePrice,
payType,
checkPeriod,
singleMoney,
periodNumber,
categoryList,
agree
} = this.state
return (
<div className='pay-order'>
<HeaderBar title='确认支付' arrow={true}></HeaderBar>
<WhiteSpace size='sm'></WhiteSpace>
<div className='order-number'>
<WingBlank>
<Flex justify='between' align='center' style={{height: '44px'}}>
<span>订单号</span>
<span className='number'>{orderId}</span>
</Flex>
</WingBlank>
</div>
<WhiteSpace size='md'></WhiteSpace>
{
categoryList.map((item, index) => {
const Info = (
<div className="order-info">
<p className='order-title text-overflow-one'>
<Link to={`/detail?id=${item.course_id}`}>{item.course_title}</Link>
</p>
<p className='order-content text-overflow-2'>{item.simpledescription}</p>
<p className='order-des'>
<span className='order-newprice'>¥{item.sale_price}</span>
<span className={'price-des'}>(预付定金)</span>
</p>
</div>
)
return (
<VList key={index} img={item.image_name}
id={item.course_id}
info={Info}></VList>
)
})
}
<WhiteSpace size='md'></WhiteSpace>
<div className='order-number'>
<WingBlank>
<Flex justify='between' align='center' style={{height: '44px'}}>
<span>支付金额</span>
<span className='money'>{`¥${salePrice}`}</span>
</Flex>
</WingBlank>
</div>
<WhiteSpace size='md'></WhiteSpace>
<List renderHeader={() => '支付方式'} className='pay-type-list'>
{mockData.map(i => (
<RadioItem
thumb={<i className={`iconfont ${i.icon} ${payType === i.value ? 'checked' : ''}`}></i>}
key={i.value}
checked={payType === i.value}
onChange={() => this.onChange(i.value)}>
{
i.value === 2 ? (
<Flex direction='column' align='start' style={{width: '100%', marginTop: '6px'}}>
<Flex direction='row' justify='between'
style={{width: '100%', paddingRight: '30px'}}>
<span style={{color: '#555555', fontSize: '14px'}}>{i.label}</span>
{
checkPeriod ? (
<span style={{
color: '#333333',
fontSize: '12px'
}}>{`${singleMoney}元 × ${periodNumber}期`}</span>
) : null
}
</Flex>
<Flex justify='start'>
<span style={{color: '#999999', fontSize: '12px'}}>支付上限受限于您的花呗额度</span>
</Flex>
</Flex>
) : (i.label)
}
</RadioItem>
))}
</List>
<Flex>
<Flex.Item className={'agreement'}>
<Checkbox.AgreeItem onChange={this.changeAgreement}>
我已同意定金不退
</Checkbox.AgreeItem>
</Flex.Item>
</Flex>
{/*<div className='pay-tip'>请在15分钟内完成支付,否则届时系统将关闭该订单。</div>*/}
<div className={classnames(['pay-button', !agree && 'invalid'])} onClick={this.pay}>确认支付</div>
</div>
)
}
}
export default WithFullSize(PayOrder)
.pay-order {
width: 100%;
height: calc(100% - 44px);
background-color: #f5f5f5;
.order-number {
background-color: #fff;
span {
font-size: 15px;
color: #333333;
}
.number {
font-size: 12px;
color: #666666;
}
.money {
color: #ff3131;
}
}
.pay-type-list {
.am-list-body {
&::after {
display: none;
}
}
.am-list-header {
color: #333333;
font-size: 15px;
background-color: #fff;
}
.iconalipay {
font-size: 22px;
color: #01aaef;
}
.iconweixinzhifu {
font-size: 22px;
color: #3baf34;
}
.iconhuabei {
font-size: 22px;
color: #01aaef;
}
.am-radio-inner {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #c1c1c1;
}
.am-radio-inner:after {
display: block;
border-color: #fff;
top: 0;
right: 6px;
}
.am-radio.am-radio-checked .am-radio-inner {
background-color: #009aff;
border-radius: 50%;
width: 20px;
height: 20px;
}
.am-radio.am-radio-checked .am-radio-inner:after {
display: block;
}
}
.agreement {
margin-top: 8px;
background: #fff;
.am-checkbox-agree{
.am-checkbox {
left: unset;
right: 6px;
}
.am-checkbox-agree-label{
margin-left: 3px;
}
}
}
.pay-tip {
width: 100%;
height: 30px;
line-height: 30px;
text-align: center;
font-size: 12px;
color: #ff3131;
background-color: #fff4ce;
}
.pay-button {
position: fixed;
bottom: 0;
width: 100%;
height: 44px;
line-height: 44px;
text-align: center;
color: #fff;
font-size: 18px;
background-color: #18b4ed;
z-index: 9;
&.invalid{
background: #BBB;
}
}
.check-staging {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, $alpha: 0.6);
z-index: 19;
.container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
border-radius: 6px;
background-color: #FFF;
padding-bottom: 10px;
.check-title {
color: #333333;
font-size: 16px;
text-align: center;
width: 100%;
height: 44px;
line-height: 44px;
border-bottom: 1px solid #DDDDDD;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
}
.am-list-item .am-list-line .am-list-extra {
flex-basis: 16%;
}
.am-radio-inner {
width: 20px;
height: 20px;
border-radius: 50%;
border: 1px solid #BFBFBF;
background-color: #fff;
}
.am-radio-inner:after {
display: block;
border-color: #fff;
top: 0;
right: 6px;
}
.am-radio.am-radio-checked .am-radio-inner {
background-color: #009aff;
border: 1px solid #FFF;
border-radius: 50%;
width: 20px;
height: 20px;
}
.am-radio.am-radio-checked .am-radio-inner:after {
display: block;
}
}
.order-info {
position: relative;
flex: 1;
.order-title {
font-size: 16px;
color: $color_333;
}
.order-content {
font-size: 14px;
color: $color_666;
margin-top: 14px;
line-height: 18px;
}
.order-des {
height: 24px;
line-height: 33px;
position: absolute;
bottom: 0;
.order-newprice {
font-size: 16px;
color: $redprice;
}
.order-price {
font-size: 12px;
color: $color_999;
margin-left: 15px;
text-decoration: line-through;
}
}
}
.v-list-item {
padding: 10px 15px;
background-color: #fff;
.content {
border: none;
padding-bottom: 0;
.cover {
flex: inherit;
width: 42.2%;
img {
width: 100%;
height: 100%;
}
.course-status {
background-color: rgba(224, 46, 36, 0.6);
}
}
.price-des {
color: #999;
font-size: 11px;
}
}
.info {
width: 52.3%;
position: relative;
display: block;
.title {
font-size: 16px;
color: $color_333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
height: 16px;
line-height: 16px;
}
.contact {
font-size: 14px;
color: $color_666;
margin-top: 14px;
}
.des {
position: absolute;
bottom: 0;
.course-price {
.price {
color: $red;
font-size: 12px;
}
.new {
color: $red;
font-size: 16px;
}
.old {
color: $color_999;
font-size: 12px;
display: inline-block;
margin-left: 15px;
text-decoration: line-through;
}
}
.isbuy {
display: inline-block;
width: 61px;
height: 18px;
background-color: $bg_active;
border-radius: 9px;
color: $white;
font-size: 12px;
text-align: center;
line-height: 18px;
}
}
}
}
}
import React, { Component } from 'react'
import { Checkbox, Flex, List, Radio, Toast, WhiteSpace, WingBlank } from 'antd-mobile'
import { browser, getParam, http, is_weixin } from '@/utils'
import { HeaderBar } from '@common/index'
import VlistBase from '@/common/v-list-base'
import './index.scss'
import { WithFullSize } from '@/HOCs'
import { Link } from "react-router-dom"
import app from "@/utils/app"
const RadioItem = Radio.RadioItem
const Item = Flex.Item
function OrderList({courses, toggleSelectedCourse}) {
return (
<Flex wrap={'wrap'}>
{courses.length && courses.map(course => {
const {image_name: img, course_id, coupon_desc, coupon_num} = course
const info = (
<div className="info">
<div className="title">{course.course_title}</div>
<div className="des">
<div className={'deposit-discount'}>
定金折扣:<span className={'price'}>-¥{course.deduction_amount}</span>
</div>
{
course.coupon_amount != 0 &&
<div className={'coupon-amount'}>
使用优惠券:<span className={'price'}>-¥{course.coupon_amount}</span>
</div>
}
</div>
<div className="prices">
<span className={'sale-price price'}>¥{course.sale_price}</span>
<span className={'former-price'}>¥{course.price1}</span>
</div>
</div>
)
return (
<React.Fragment key={course.course_id}>
<Item className={'order-item'}>
<Flex className="select-bar" justify={'between'}>
<Item>
<Checkbox defaultChecked onChange={() => {
toggleSelectedCourse(course)
}}/>
</Item>
<Item className={'final-payment-hint'}>
待付尾款
</Item>
</Flex>
<VlistBase img={img}
handleClick={() => {
}}
info={info}
/>
</Item>
<div className="order-prefer">
<List key={course_id}>
<List.Item
arrow="horizontal"
onClick={() => {
}}
>
<Link to={{
pathname: `/coupons`,
search: `?id=${course_id}`,
state: {
from: '/order'
}
}}>
<Flex justify='between'>
<span
style={{
color: '#333',
fontSize: '15px'
}}
>优惠券</span>
<span
style={{
fontSize: '14px',
color: '#999999'
}}
>
{!coupon_desc ? (coupon_num === 0 ? '无' : `${coupon_num}张可用`) : (coupon_desc)}
</span>
</Flex>
</Link>
</List.Item>
</List>
</div>
</React.Fragment>
)
})}
</Flex>
)
}
let mockData = []
if (browser.isWeixin) {
mockData = [
{value: 1, label: '微信支付', icon: 'iconweixinzhifu'}
]
} else {
mockData = [
{value: 1, label: '微信支付', icon: 'iconweixinzhifu'},
{value: 0, label: '支付宝', icon: 'iconalipay'},
]
}
class FinalDepositOrder extends Component {
constructor(props) {
super(props)
this.state = {
pay_amount: 0,
payType: 1,
stageNumber: 0,
orderId: getParam('oid'),
categoryList: [],
selectedCourses: [],
salePrice: '',
user_account: '',
useBalance: false,
info: false,
order_id: '',
moneyOffRules: [],
finalEndTime: '',
offset: 0,
appliedMoneyOffRule: {}
}
}
onChange = (value) => {
this.setState({
payType: value,
checkPeriod: false,
})
if (value === 2) {
this.setState({
huabei: true,
})
}
}
// 确定购买
pay = () => {
const {payType, order_id} = this.state
if (payType === 0) {
this.alipayPay(order_id)
} else if (payType === 1) {
this.weixinPay(order_id)
}
}
//提交
submit = () => {
this.createOrder().then(res => {
if (res.data.errno == 200) {
this.setState({
order_id: res.data.data.order_id
}, () => {
if (res.data.data.pay_jump === 1) {
this.props.history.push('/purchased')
} else {
this.pay()
}
})
} else {
Toast.info(res.data.msg)
}
})
}
//创建订单
createOrder = () => {
const {selectedCourses, salePrice, useBalance, user_account} = this.state
return http.post(`${API["base-api"]}/m/deposit/final/create`, {
course_ids: selectedCourses.map(item => item.course_id),
cut_amount: 0,
pay_amount: salePrice,
is_deduction: useBalance ? 1 : 0,
deduction_amount: useBalance ? this.getBalanceOffset() : 0,
plat_form: 5,
source: getParam('source')
})
}
// 微信支付
weixinPay = (orderId) => {
// 微信内部-支付
if (is_weixin()) {
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(window.location.href + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"
} else {
// 微信外部-支付
http.get(`${API['base-api']}/pay/wxpay/wap_charge/oid/${orderId}`).then((res) => {
if (res.data.errno === 0) {
window.location.href = res.data.data.url + "&redirect_url=" + encodeURIComponent(window.location.href + "&weixinpay=1").toLowerCase()
} else {
Toast.info(res.data.msg, 2)
}
})
}
}
// 微信内部支付
isweixinPay = () => {
let _this = this
let weixin_code = getParam('code')
if (weixin_code) {
if (getParam('oid') === undefined) {
return
} else {
http.get(`${API['base-api']}/pay/wxpay/pub_charge/oid/${getParam('oid')}/code/${weixin_code}`).then((res) => {
if (res.data.errno === 0) {
let data = res.data.data
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
appId: data.appId, //公众号名称,由商户传入
timeStamp: data.timeStamp, //时间戳,自1970年以来的秒数
nonceStr: data.nonceStr, //随机串
package: data.package,
signType: data.signType, //微信签名方式:
paySign: data.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
Toast.info('支付成功', 2)
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus)
_this.intervalPayStatus = null
_this.props.history.replace(`/expand/callback?order_id=${getParam('oid')}`)
}
})
}, 1000)
} else {
alert('支付失败')
}
}
)
}
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false)
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady)
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady)
}
} else {
onBridgeReady()
}
} else {
Toast.info(res.data.msg, 2)
}
})
}
}
}
// 支付完成之后获取状态
payCallback = () => {
const _this = this
// 支付回调
// 定时器轮训获取订单状态
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus)
_this.intervalPayStatus = null
window.location.href = '/expand/callback?order_id=' + getParam('oid')
}
})
}, 1000)
}
// 支付宝支付
alipayPay = (orderId) => {
http.get(`${API['base-api']}/pay/alipay/wap_charge_new/oid/${orderId}`).then((res) => {
if (res.data.errno === 0) {
this.payCallback()
window.location = res.data.data.url
} else {
Toast.info(res.data.msg, 2)
}
})
}
componentDidMount() {
if (getParam('weixinpay')) {
this.payCallback()
}
if (browser.isWeixin) {
this.isweixinPay(getParam('oid'))
}
http.get(`${API["base-api"]}/m/deposit/final/preorder`)
.then(res => {
const {data} = res
if (data.errno == 200) {
this.setState({
categoryList: [...data.data.courses],
salePrice: this.getTotalPrice({
courses: [...data.data.courses],
moneyOffRules: data.data['full_rule']
}),
selectedCourses: [...data.data.courses],
user_account: data.data.user_account,
moneyOffRules: data.data['full_rule'],
finalEndTime: data.data['final_end_time']
})
} else {
Toast.info(data.msg)
}
})
}
// 展示余额抵扣规则
showInfo = () => {
this.setState((prevState) => ({
info: !prevState.info
}))
}
toggleSelectedCourse = course => {
this.setState(prevState => {
const {selectedCourses} = prevState
let index = prevState.selectedCourses.findIndex(item => item.course_id == course.course_id)
if (index == -1) {
selectedCourses.push(course)
} else {
selectedCourses.splice(index, 1)
}
let totalPrice = this.getTotalPrice(selectedCourses)
return {selectedCourses, salePrice: totalPrice, offset: this.getBalanceOffset(totalPrice)}
})
}
//获取支付价格
getTotalPrice = (
{
courses = this.state.selectedCourses,
useBalance = this.state.useBalance,
moneyOffRules = this.state.moneyOffRules
} = {}
) => {
let totalPrice = this.getOriginTotalPrice({courses})
totalPrice = this.moneyOff(totalPrice, moneyOffRules)
if (useBalance) {
totalPrice -= parseFloat(this.state.user_account)
}
return totalPrice < 0 ? 0 : totalPrice.toFixed(2)
}
//满减计算
moneyOff = (totalPrice, moneyOffRules = this.state.moneyOffRules) => {
let rules = moneyOffRules.sort((a, b) => b.full_amount - a.full_amount)
let result = parseFloat(totalPrice)
for (let i = 0; i < rules.length; i++) {
let rule = rules[i]
if (result >= rule.full_amount) {
this.setState({
appliedMoneyOffRule: rule
})
return result - parseFloat(rule.cut_amount)
}
}
return result
}
//使用余额
useBalance = () => {
this.setState(prevState => {
const useBalance = !prevState.useBalance
let totalPrice = this.getTotalPrice({useBalance})
return {
useBalance,
salePrice: totalPrice,
offset: this.getBalanceOffset(totalPrice)
}
})
}
getOriginTotalPrice = ({courses = this.state.selectedCourses} = {}) => {
return courses.reduce((accu, item) => {
return accu + parseFloat(item['sale_price'])
}, 0)
}
getBalanceOffset = () => {
let originalTotalPrice = this.getOriginTotalPrice()
let offset = parseFloat(this.state.user_account) - parseFloat(originalTotalPrice)
offset = offset >= 0 ? originalTotalPrice : this.state.user_account
return offset
}
render() {
const {
orderId,
salePrice,
payType,
categoryList,
user_account,
useBalance,
info,
finalEndTime,
offset,
appliedMoneyOffRule
} = this.state
return (
<div className='deposit-pay-order'>
<HeaderBar title='课程报名' arrow={true}></HeaderBar>
<WhiteSpace size='sm'></WhiteSpace>
{/*<div className='order-number'>
<WingBlank>
<Flex justify='between' align='center' style={{height: '44px'}}>
<span>订单号</span>
<span className='number'>{orderId}</span>
</Flex>
</WingBlank>
</div>*/}
<WhiteSpace size='md'></WhiteSpace>
<div className={'order-list'}>
<OrderList courses={categoryList}
toggleSelectedCourse={this.toggleSelectedCourse}
/>
</div>
<div className="order-balance">
<List>
<Item
className="order-prefer-text"
>
<Flex justify='between'>
<Flex align='center'>
<span>余额抵扣</span>
<span className="order-balanceprice"> (余额: <i
className="order-money">{`${user_account}元`}</i>)</span>
<i className="iconfont iconiconfront-22 question-mark" onClick={this.showInfo}></i>
</Flex>
<Flex>
{
useBalance ? (
<>
<span style={{
color: '#FF2121',
fontSize: '15px',
marginRight: "6px"
}}>{`-¥${offset}`}</span>
<i className={`iconfont icondanseshixintubiao-5 balance-used`}
onClick={this.useBalance}></i>
</>
) : (
<i className='circle-icon' onClick={this.useBalance}></i>
)
}
</Flex>
</Flex>
</Item>
</List>
</div>
<WhiteSpace size='md'></WhiteSpace>
<div className='order-number'>
<WingBlank>
<Flex justify='between' align='center' style={{height: '44px'}}>
<span>支付金额</span>
<span className='money'>{`¥${salePrice}`}</span>
</Flex>
</WingBlank>
</div>
<WhiteSpace/>
{
appliedMoneyOffRule.full_amount &&
<div className="money-off">
<WingBlank>
<Flex justify='end' align='center' style={{height: '44px'}}>
<span>{appliedMoneyOffRule.full_amount}{appliedMoneyOffRule.cut_amount}</span>
<span className='money'>{`-¥${appliedMoneyOffRule.cut_amount}`}</span>
</Flex>
</WingBlank>
</div>
}
<WhiteSpace size='md'></WhiteSpace>
<List renderHeader={() => '支付方式'} className='pay-type-list'>
{mockData.map(i => (
<RadioItem
thumb={<i className={`iconfont ${i.icon} ${payType === i.value ? 'checked' : ''}`}></i>}
key={i.value}
checked={payType === i.value}
onChange={() => this.onChange(i.value)}>
{i.label}
</RadioItem>
))}
</List>
<div className='pay-tip'>{`${finalEndTime}结束支付尾款`}</div>
<div className='pay-button' onClick={this.submit}>确认支付</div>
{
info ? (
<div style={{
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
zIndex: '99'
}}>
<div style={{
padding: '20px',
backgroundColor: '#FFF',
width: '300px',
height: '170px',
margin: '0 auto',
position: 'absolute',
left: '50%',
top: '50%',
transform: 'translate(-50%, -50%)'
}}>
<Flex direction='column' justify='between' align='center' style={{height: '100%'}}>
<p style={{fontSize: '16px', color: '#333333'}}>余额抵扣说明</p>
<p style={{
lineHeight: '20px',
fontSize: '13px',
color: '#666666'
}}>分销课程或者参与七月在线的相关活动,可获得资金奖励。账户资金可直接提现,也可抵扣课程费用。</p>
<div onClick={this.showInfo} style={{
width: '260px',
height: '30px',
lineHeight: '30px',
textAlign: 'center',
borderRadius: '3px',
border: '1px solid #0099FF',
color: '#0099FF',
fontSize: '15px'
}}>知道了
</div>
</Flex>
</div>
</div>
) : null
}
</div>
)
}
}
export default WithFullSize(FinalDepositOrder)
.deposit-pay-order {
width: 100%;
background-color: #f5f5f5;
box-sizing: content-box;
padding-bottom: 44px;
.order-number {
background-color: #fff;
span {
font-size: 15px;
color: #333333;
}
.number {
font-size: 12px;
color: #666666;
}
.money {
color: #ff3131;
}
}
.money-off{
font-size: 14px;
background: #fff;
color: #999;
.money{
color: #FF3131;
}
}
.pay-type-list {
.am-list-body {
&::after {
display: none;
}
}
.am-list-header {
color: #333333;
font-size: 15px;
background-color: #fff;
}
.iconalipay {
font-size: 22px;
color: #01aaef;
}
.iconweixinzhifu {
font-size: 22px;
color: #3baf34;
}
.iconhuabei {
font-size: 22px;
color: #01aaef;
}
.am-radio-inner {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #c1c1c1;
}
.am-radio-inner:after {
display: block;
border-color: #fff;
top: 0;
right: 6px;
}
.am-radio.am-radio-checked .am-radio-inner {
background-color: #009aff;
border-radius: 50%;
width: 20px;
height: 20px;
}
.am-radio.am-radio-checked .am-radio-inner:after {
display: block;
}
}
/*.agreement {
margin-top: 8px;
background: #fff;
.am-checkbox-agree{
.am-checkbox {
left: unset;
right: 6px;
}
.am-checkbox-agree-label{
margin-left: 3px;
}
}
}*/
.price {
color: #FF3131;
margin-right: 10px;
font-size: 12px;
&.sale-price {
font-size: 15px;
}
}
.former-price {
text-decoration: line-through;
color: #999;
}
.pay-tip {
width: 100%;
padding: 21px;
text-align: center;
font-size: 12px;
color: #ff3131;
}
.pay-button {
position: fixed;
bottom: 0;
width: 100%;
height: 44px;
line-height: 44px;
text-align: center;
color: #fff;
font-size: 18px;
background-color: #18b4ed;
z-index: 9;
}
.check-staging {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, $alpha: 0.6);
z-index: 19;
.container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
border-radius: 6px;
background-color: #FFF;
padding-bottom: 10px;
.check-title {
color: #333333;
font-size: 16px;
text-align: center;
width: 100%;
height: 44px;
line-height: 44px;
border-bottom: 1px solid #DDDDDD;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
}
.am-list-item .am-list-line .am-list-extra {
flex-basis: 16%;
}
.am-radio-inner {
width: 20px;
height: 20px;
border-radius: 50%;
border: 1px solid #BFBFBF;
background-color: #fff;
}
.am-radio-inner:after {
display: block;
border-color: #fff;
top: 0;
right: 6px;
}
.am-radio.am-radio-checked .am-radio-inner {
background-color: #009aff;
border: 1px solid #FFF;
border-radius: 50%;
width: 20px;
height: 20px;
}
.am-radio.am-radio-checked .am-radio-inner:after {
display: block;
}
}
.select-bar {
background: #fff;
padding: 11px 15px;
border-bottom: 1px solid #E5E5E5;
.am-flexbox-item {
flex: 0 1 auto;
}
.final-payment-hint {
padding: 4px 6px 5px;
background: $bg-active;
border-radius: 3px;
color: #fff;
}
}
.order-item {
}
.v-list-base-item {
padding: 10px 15px;
background-color: #fff;
.content {
border: none;
padding-bottom: 0;
.cover {
flex: inherit;
width: 42.2%;
img {
width: 100%;
height: 100%;
}
.course-status {
background-color: rgba(224, 46, 36, 0.6);
}
}
.price-des {
color: #999;
font-size: 11px;
}
}
.info {
width: 52.3%;
position: relative;
.title {
font-size: 15px;
color: $color_333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
height: 16px;
line-height: 16px;
margin-bottom: 16px;
}
.contact {
font-size: 14px;
color: $color_666;
margin-top: 14px;
}
.des {
color: #999;
.course-price {
.price {
color: $red;
font-size: 12px;
}
.new {
color: $red;
font-size: 16px;
}
.old {
color: $color_999;
font-size: 12px;
display: inline-block;
margin-left: 15px;
text-decoration: line-through;
}
}
.isbuy {
display: inline-block;
width: 61px;
height: 18px;
background-color: $bg_active;
border-radius: 9px;
color: $white;
font-size: 12px;
text-align: center;
line-height: 18px;
}
}
& .prices:last-child {
position: absolute;
bottom: 0;
}
}
}
//order.scss
.order-balance {
height: 44px;
line-height: 44px;
padding: 0 15px;
background: #fff;
.am-list-item {
padding-left: 0 !important;
}
.am-list-line {
padding: 0 15px;
}
.am-list-content {
color: $color_333;
font-size: $font_16;
.iconiconfront-22 {
font-size: 18px;
margin-left: 15px;
}
}
.order-balanceprice {
color: $color_666;
font-size: $font_12;
.order-money {
color: #ff2121;
font-size: $font_12 !important;
font-weight: normal;
font-style: inherit;
vertical-align: middle;
margin: 0;
}
}
.iconiconfront-22.question-mark {
font-size: 24px;
margin-left: 15px;
}
.am-list-body {
&::before, &::after {
display: none;
}
}
.balance-used {
font-size: 24px;
color: #0099FF;
}
.circle-icon {
width: 20px;
height: 20px;
border: 1px solid #BFBFBF;
border-radius: 50%;
margin-right: 2px;
}
}
.order-prefer {
width: 100%;
margin-bottom: 6px;
.am-list-body {
&::after {
display: none;
}
}
.am-list-content {
font-size: 15px !important;
}
}
.order-list{
.am-flexbox-item{
margin-left: 0;
}
}
/*.order-tab {
color: $black;
background: $bg_f7f9fc;
}
.order-information {
display: flex;
width: 100%;
overflow: hidden;
padding: 29px 15px;
color: $color_555;
background-color: $bg_fff;
position: relative;
}
.order-information::before {
content: '';
left: 0;
right: 0;
bottom: 0;
height: 2px;
position: absolute;
background: -webkit-repeating-linear-gradient(135deg, #ff6c6c 0, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
background: repeating-linear-gradient(-45deg, #ff6c6c 0, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
background-size: 80px;
}
.order-information2 {
height: 80px;
background-color: #FFF;
margin-top: 8px;
position: relative;
.user-icon {
font-size: 28px;
flex-basis: 40px;
}
.order-cell {
height: 50px;
font-size: 13px;
color: $color_333;
line-height: 20px;
flex: 1 1 auto;
.name {
margin-bottom: 10px;
}
}
}
.order-information2::before {
content: '';
left: 0;
right: 0;
bottom: 0;
height: 2px;
position: absolute;
background: -webkit-repeating-linear-gradient(135deg, #ff6c6c 0, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
background: repeating-linear-gradient(-45deg, #ff6c6c 0, #ff6c6c 20%, transparent 0, transparent 25%, #1989fa 0, #1989fa 45%, transparent 0, transparent 50%);
background-size: 80px;
}
.order-addsize {
font-size: 22px !important;
margin-bottom: 0px;
height: 22px;
color: $active;
line-height: 22px;
}
.order-next {
line-height: 22px;
margin-bottom: 0px;
}
.order-list {
margin-top: 8px;
background-color: #F5F5F5;
.public-content {
padding: 10px 15px;
}
}
.order-infotext {
flex: 1;
height: 22px;
line-height: 22px;
margin-left: 10px;
font-size: $font_14;
color: $color_555;
}
.order-info {
color: $color_666;
font-size: $font_14;
min-width: 160px;
flex: 1 1 auto;
display: flex;
flex-direction: column;
justify-content: space-around;
.order-title {
color: $color_333;
font-size: $font_16;
}
.order-content {
color: $color_666;
font-size: $font_14;
line-height: 18px;
}
.order-newprice {
color: $redprice;
font-size: $font_16;
margin-right: 15px;
}
.order-price {
color: $color_999;
font-size: $font_12;
text-decoration: line-through;
}
}
.order-bar {
width: 100%;
position: fixed;
bottom: 0;
z-index: 2;
height: 50px;
display: flex;
font-size: 14px;
align-items: center;
background-color: $bg_fff;
}
.order-course {
margin-left: 20px;
.order-course-text {
font-size: $font_16;
color: $color_333;
}
}
.order-bar-text {
flex: 1;
text-align: right;
color: #323233;
padding-right: 20px;
.order-amount {
font-size: $font_14;
color: $color_333;
.order-amount-price {
color: $redprice;
}
}
.order-preprice {
font-size: $font_12;
color: $color_555;
}
}
.order-button {
width: 110px;
height: 50px;
display: inline-block;
padding: 0;
background-color: $bg_ff9898;
color: $white;
line-height: 48px;
font-size: 16px;
border-radius: 0px;
text-align: center;
box-sizing: border-box;
-webkit-appearance: none;
-webkit-text-size-adjust: 100%;
border: 1px solid transparent;
}
.has-info {
background-color: #FF3131;
}
.am-list-item .am-list-line .am-list-content {
color: $color_333;
}
.order-list {
.am-list-item {
padding-left: 0 !important;
}
}
*/
}
......@@ -120,6 +120,8 @@ class Order extends Component {
orderList: [],
info: false,
offset: 0,
full_amount: 0, // 满金额
cut_amount: 0, // 减金额
};
}
// 提交订单
......@@ -267,6 +269,12 @@ class Order extends Component {
discount,
});
};
fullRules = (data) => {
this.setState({
full_amount: data.full_amount,
cut_amount: data.cut_amount,
});
};
// 公共方法 本地存储
publicLocalStorage = () => {
if(this.props.history.action === 'PUSH') {
......@@ -300,8 +308,11 @@ class Order extends Component {
// 普通课程立即报名 不带 type = 1
http.get(`${API['base-api']}/m/order/preorder`).then(res => {
if(res.data.errno === 200) {
console.log(res.data.data);
this.publicGetData(res.data.data);
this.publicLocalStorage();
this.fullRules(res.data.data);
}else{
Toast.info(res.data.msg, 2);
}
......@@ -407,7 +418,9 @@ class Order extends Component {
useBalance,
info,
offset,
groupPrice
groupPrice,
full_amount,
cut_amount,
} = this.state;
return (
......@@ -495,6 +508,20 @@ class Order extends Component {
</Item>
</List>
</div>
{
(full_amount > 0 && cut_amount > 0) ? (
<>
<div className="full__rules">
<WingBlank>
<div className="money__off">
<span>{full_amount}{cut_amount}</span>
<span className='money'>{`-¥${cut_amount}`}</span>
</div>
</WingBlank>
</div>
</>
) : (null)
}
<div className="order-bar">
<div className="order-course">
<span className="order-course-text">{`${orderList.length}门课程`}</span>
......@@ -545,4 +572,4 @@ class Order extends Component {
}
export default Order;
\ No newline at end of file
export default Order;
......@@ -265,7 +265,8 @@
.order-balance {
height: 44px;
line-height: 44px;
margin: 8px 0 50px 0;
margin: 8px 0 8px 0;
display: flow-root;
.am-list-item {
padding-left: 0 !important;
......@@ -282,4 +283,23 @@
}
}
}
.full__rules {
width: 100%;
height: 50px;
margin-top: 16px;
background: #FFF;
font-size: 14px;
background: #fff;
color: #999;
.money__off {
height: 50px;
display: flex;
justify-content: space-between;
align-items: center;
}
.money{
color: #FF3131;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment