react-app-shell
Version:
react打包脚本和example, 这里的版本请忽略
374 lines (353 loc) • 11.3 kB
JavaScript
// 功能方法>>>引用:
import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';
import classNames from 'classnames';
// 公用方法 配置项 接口 枚举>>>引用:
import { message, monitor, tools } from '../../utils';
import { appConfig } from '../../config';
import { orderService, landingPageService } from '../../service';
import {
LANDING_ACTIVITY_STATUS,
LANDING_BUY_STATUS,
LANDING_ERROR_CODE
} from '../../constants/landing';
import { AccountsType } from '../../constants';
// 组件 公用组件>>>引用:
import { ServiceError } from '../common';
import CountDown from './count-down';
import MoneyBlock from './money-block';
import AboutClass from './about-class';
import ContentImg from './content-img';
import {
checkUserAuth,
ModalLogin,
WechatConfig,
InfoModal,
DocumentTitle
} from '../../components';
// 样式>>>引用:
import styles from './landing.less';
(({ landingStore }) => {
return {
// 数据
configId: landingStore.state.configId, // 配置id
img: landingStore.state.bannerImgUrl, // banner图
endTime: landingStore.state.endTime, // 倒计时时间
nowTime: landingStore.state.nowTime, // 服务器现在时间
buttonImg: landingStore.state.buttonImg, // 按钮背景图
productCourse: landingStore.state.productCourse, // 价格和有效期
mainImg: landingStore.state.mainImg, // 内容区域图
activeState: landingStore.state.activeState, // 活动状态
buyStatus: landingStore.state.buyStatus, // 购买状态
shareOptions: landingStore.state.shareOptions, // 分享数据
serviceError: landingStore.state.serviceError, // 网络错误显示该组件
// 函数
initData: landingStore.initData // 初始化方法
};
})
({
account: AccountsType.MAIN,
support: 'all'
}) // 微信授权--魔力耳朵公众号
export default class Landing extends Component {
constructor(props) {
super(props);
const id = this.props.match.params.id;
this.state = {
id,
title: '魔力耳朵少儿英语',
modalKey: '', // 弹窗的key
landingUrl: `${appConfig.domain.mobileDomain}${appConfig.basename}/landing/${id}` // 登陆后回调到本页的url
};
const { initData } = this.props;
// 初始化数据
initData(id);
// 简单节流
this.throttleHandleClick = tools.throttle(this.handleAllowJoin, 1500); // 限时抢购
this.throttleAddAds = tools.throttle(this.handelAddAds, 1500); // 提示弹窗回调确认
}
componentDidMount() {
// 埋点浏览人数
monitor.log('', 'landing >> 浏览低价课引流页面');
// 埋点渠道码
this.rfcodeLandingQuantity();
}
/**
* 渠道码埋点
*/
rfcodeLandingQuantity = () => {
if (Number(tools.getQueryString('rf')) !== -1 && tools.getQueryString('rf')) {
// 渠道码默认-1无效, 只统计有效渠道码
monitor.log('', `landing >> 低价课引流页面渠道码: ${tools.getQueryString('rf')}`);
}
};
/**
* 点击购买次数/人数埋点
*/
enterLandingQuantity = () => {
monitor.log('', 'landing >> 点击购买次数');
if (!window.localStorage.enterlanding) {
// 通过localStorage做埋点人数统计
window.localStorage.setItem('enterlanding', 'landing');
monitor.log('', 'landing >> 点击购买人数');
}
};
/**
* 限时抢购按钮
*/
handleAllowJoin = () => {
message.showLoading();
this.enterLandingQuantity(); // 对页面点击购买次数和人数进行埋点
const { id } = this.state;
const { initData } = this.props;
landingPageService
.getLandingPageActivity(id)
.then(() => {
this.handleBuy(); // 如果登陆就直接生成订单, 如果没登陆 去登陆, 此方法用在登陆后回调
})
.catch(({ code, msg }) => {
message.closeLoading();
// TODO >>> switch case
switch (code) {
case LANDING_ERROR_CODE.LOGIN_REQUIRED:
this.setState({
modalKey: 'Login'
});
return;
case LANDING_ERROR_CODE.BIZ_LOW_PRIZE_COURSE_NOT_EXIST:
this.setState({
modalKey: 'Nothing'
});
return;
case LANDING_ERROR_CODE.BIZ_LOW_PRIZE_COURSE_BUY_FINISH:
initData(id); // 用户已购买该课程, 不弹窗, 直接初始化页面
return;
case LANDING_ERROR_CODE.BIZ_LOW_PRIZE_COURSE_USER_PAID:
this.setState({
modalKey: 'Paid'
});
return;
case LANDING_ERROR_CODE.BIZ_LOW_PRIZE_COURSE_USER_SHEEP:
this.setState({
modalKey: 'Sheep'
});
return;
default:
monitor.log('', `landing >> join 获取用户是否可参加活动失败, ${msg}`);
message.error(msg || '发生错误!');
}
});
};
/**
* 登录/注册成功的回调
*/
handleLoginCallback = () => {
this.setState({
modalKey: ''
});
this.handleAllowJoin();
};
/**
* 关闭modal
*/
handleHideModal = () => {
this.setState({
modalKey: ''
});
};
/**
* 生成订单
*/
handleBuy = async () => {
const { landingUrl } = this.state;
const {
productCourse: { productId }
} = this.props;
// 创建订单, 并跳转到订单页面
orderService
.createOrder(productId)
.then((orderNo) => {
message.closeLoading();
monitor.log('', `landing >> 提交订单成功, 订单号: ${orderNo}`);
const url = `${appConfig.domain.mobileDomain}/pay/order_info?channel=wechat&type=WechatMP&order_no=${orderNo}&callback_url=${landingUrl}`;
window.location.href = url;
})
.catch(({ code, msg }) => {
message.closeLoading();
// 如果用户未登录或者登录失效, 需要重新登录
if (code && code === LANDING_ERROR_CODE.LOGIN_REQUIRED) {
monitor.log('', 'landing >> 登录状态过期, 需要重新登录');
this.setState({
modalKey: 'Login'
});
return;
}
monitor.log('', `landing >> 创建订单失败, ${msg}`);
message.error(msg || '发生错误! 购买失败');
});
};
/**
* 页面底部按钮显示
*/
showBtnForStatus = () => {
const { activeState, buttonImg } = this.props;
const btnBg = {
backgroundImage: 'url(' + buttonImg + ')',
backgroundSize: '100%'
};
switch (activeState) {
case LANDING_ACTIVITY_STATUS.ACTIVITY_NOT_START:
return <div className={classNames(styles.pageBtn, styles.pageBtnGray)}>活动未开始</div>;
case LANDING_ACTIVITY_STATUS.ACTIVITY_PROCESSING:
return (
<div
style={btnBg}
className={classNames(styles.pageBtn, styles.pageBtnAni)}
onClick={this.throttleHandleClick}
>
限时秒杀 立即抢购
</div>
);
case LANDING_ACTIVITY_STATUS.ACTIVITY_END:
return <div className={classNames(styles.pageBtn, styles.pageBtnGray)}>活动已结束</div>;
default:
return null;
}
};
/**
* 弹窗render
* Login: 登陆 业务弹窗
* Nothing: 没有配置 提示弹窗
* Paid: 付费用户 提示弹窗
* Sheep: 羊毛妈妈 提示弹窗
*/
renderModal = () => {
const { id, modalKey } = this.state;
switch (modalKey) {
case 'Login':
return (
<ModalLogin
onOk={this.handleLoginCallback}
onCancel={this.handleHideModal}
actId={id}
actType="landing"
></ModalLogin>
);
case 'Nothing':
return (
<InfoModal
headerType="weep"
cancelVisible={false}
onOk={this.throttleAddAds}
okBtnStyle={{
background: 'linear-gradient(90deg,rgba(255,132,44,1) 0%,rgba(255,107,44,1) 100%)',
color: '#fff'
}}
>
<div className={styles['info-notes']}>活动配置不存在~</div>
</InfoModal>
);
case 'Paid':
return (
<InfoModal
headerType="weep"
cancelVisible={false}
onOk={this.throttleAddAds}
okBtnStyle={{
background: 'linear-gradient(90deg,rgba(255,132,44,1) 0%,rgba(255,107,44,1) 100%)',
color: '#fff'
}}
>
<div className={styles['info-notes']}>啊哦,本活动仅限魔力耳朵未付费学员购买哦~</div>
</InfoModal>
);
case 'Sheep':
return (
<InfoModal
headerType="weep"
cancelVisible={false}
onOk={this.throttleAddAds}
okBtnStyle={{
background: 'linear-gradient(90deg,rgba(255,132,44,1) 0%,rgba(255,107,44,1) 100%)',
color: '#fff'
}}
>
<div className={styles['info-notes']}>
啊哦,亲爱的宝妈,您之前参加过魔力耳朵特惠活动,这次就不能参加啦~
</div>
</InfoModal>
);
default:
return null;
}
};
/**
* 配置不存在/羊毛妈妈/付费用户 确认回调
*/
handelAddAds = async () => {
const { id } = this.state;
const { initData } = this.props;
await initData(id); // 初始化页面数据
this.handleHideModal(); // 关闭弹窗
};
render() {
const { serviceError } = this.props;
// 获取信息时发生异常, 阻塞掉代码不往下走了
if (serviceError) {
return <ServiceError></ServiceError>;
}
const {
img,
endTime,
nowTime,
productCourse,
mainImg,
buyStatus,
productCourse: { productNum },
activeState,
shareOptions,
initData,
configId
} = this.props;
const { title } = this.state;
switch (buyStatus) {
case LANDING_BUY_STATUS.NO:
return (
<div className={styles.landing}>
<img className={styles.clgImg} src={img} />
<div className={styles.userContent}>
<MoneyBlock productCourse={productCourse} />
<CountDown
countDownTime={endTime}
nowTime={nowTime}
activeState={activeState}
configId={configId}
onFinish={initData}
/>
</div>
<ContentImg mainImg={mainImg}></ContentImg>
{this.showBtnForStatus()}
{this.renderModal()}
<WechatConfig showShare={true} shareOptions={shareOptions}></WechatConfig>
<DocumentTitle title={title} />
</div>
);
case LANDING_BUY_STATUS.YES:
return (
<>
<AboutClass productNum={productNum} />
<WechatConfig showShare={true} shareOptions={shareOptions}></WechatConfig>
<DocumentTitle title={title} />
</>
);
default:
return (
<>
<WechatConfig showShare={false}></WechatConfig>
<DocumentTitle title={title} />
</>
);
}
}
}