react-app-shell
Version:
react打包脚本和example, 这里的版本请忽略
770 lines (707 loc) • 23.9 kB
JavaScript
import React, { Component } from 'react';
import { observer, inject } from 'mobx-react';
import { withRouter } from 'react-router-dom';
import queryString from 'query-string';
import { WechatConfig, ModalLogin } from '../../../components';
import { SpecialGroupService, wechatService } from '../../../service';
import {
JOIN_STATUS,
GROUP_STATUS,
SYSTEM_MODAL_KEY,
CREATE_RESULT_CODE,
ALLOWFULLJOIN,
JOINCONDITION,
SPECIAL_TYPE
} from '../../../constants';
import { message, tools, monitor } from '../../../utils';
import { appConfig, shareConfig } from '../../../config';
import { CustomServiceModal, WeiXinModal, NoJoinTipsModal, ShareLayerModal } from '../../component';
import bonny from '../../../public/images/group/bonny.png';
import styles from './styles.less';
// 约课链接
const bookingUrl = appConfig.domain.mobileDomain.concat('/user/special');
/**
* 环境
* @type {string}
*/
const NODE_ENV = process.env.NODE_ENV || 'development';
/**
* 默认分享
* @type {shareConfig.group|{title, desc, imgUrl, type, dataUrl}}
*/
const defaultShareOptions = shareConfig.group;
/**
* 团购底部按钮
*/
class Footer extends Component {
constructor(props) {
super(props);
// 同步检查用户授权
// wechatUtils.checkUserAuth();
this.urlParams = queryString.parse(window.location.search);
// 获取用户的主公众号授权的openId
// this.openId = tools.getMainOpenId();
// 获取用户的魔小兔产品公众号授权的openId
this.openId = tools.getBonnyOpenId();
this.state = {
modalKey: '',
shareOptions: {
...defaultShareOptions,
link: this.getDefaultShareLink()
},
tipsText: ''
};
this.throttleCreateTeam = tools.throttle(this.handleCreateTeam, 1000);
this.throttleJoinTeam = tools.throttle(this.handleJoinTeam, 1000);
}
componentWillReceiveProps(nextProps) {
// 当团购活动Id或者teamId变化时, 重新设置分享信息
const { groupId, teamId } = this.props;
if (nextProps.groupId !== groupId || nextProps.teamId !== teamId) {
let nextTeamId = nextProps.teamId;
// 如果是单独购买, 则分享的链接里,不需要带teamId参数, 需要设置为默认值-1
if (nextProps.joinStatus === JOIN_STATUS.SINGLE_BUY) {
nextTeamId = -1;
}
this.updateShareOptions(nextProps.groupId, nextTeamId, nextProps.shareInfo);
}
}
componentDidUpdate(prevProps) {
// 如果groupId或teamId发生变化, 检查是否关注过公众号
if (this.props.groupId !== prevProps.groupId || this.props.teamId !== prevProps.teamId) {
this.checkFollow();
}
}
/**
* 获取默认分享的链接
*/
getDefaultShareLink = () => {
const { groupId, teamId, rf } = this.urlParams;
const searchObj = {
groupId,
teamId: teamId,
rf: rf || -1
};
// 分享链接
const link = `${location.protocol}//${location.host}${
location.pathname
}?${queryString.stringify(searchObj)}`;
return link;
};
/**
* 更新分享配置
* @param groupId
* @param teamId
* @param shareInfo
*/
updateShareOptions = (groupId, teamId, shareInfo = {}) => {
const searchObj = {
groupId,
teamId: teamId,
rf: this.urlParams.rf || -1
};
// 分享链接
const link = `${window.location.protocol}//${window.location.host}${
window.location.pathname
}?${queryString.stringify(searchObj)}`;
const shareOptions = {
...defaultShareOptions,
title: shareInfo.title || defaultShareOptions.title,
desc: shareInfo.desc || defaultShareOptions.desc,
imgUrl: shareInfo.imgUrl || defaultShareOptions.imgUrl,
link
};
// 更新分享内容
this.setState({
shareOptions
});
};
/**
* 引导关注公众号
* @returns {Promise<void>}
*/
checkFollow = async () => {
const {joinStatus, account} = this.props;
// const {from} = this.urlParams;
try {
// 当用户参加过团购,判断是否关注, 引导关注公众号
if (joinStatus !== JOIN_STATUS.NOT_JOIN) {
const {subscribeFlag} = await wechatService.checkWxSubscribe(account);
if (!subscribeFlag) {
this.setState({
modalKey: SYSTEM_MODAL_KEY.GROUP_SUCCESS_MODAL // 团购购买成功, 引导关注公众号
});
}
}
} catch (error) {
console.error(error);
// message.error(error.msg);
}
};
/**
* 获取支付Url
* @param orderNo 订单号
* @param teamId 开团/单独购买的链接不需要传teamId参数
* @returns {string}
*/
getPayUrl = (orderNo, teamId) => {
const { groupId } = this.props;
const { rf } = this.urlParams;
const searchObj = {
groupId,
teamId: teamId,
rf: rf || -1,
from: 'pay' // 支付成功之后跳转回来, 根据该字段去判断是否关注过公众号
};
const callbackUrl = encodeURIComponent(
`${window.location.protocol}//${window.location.host}${
window.location.pathname
}?${queryString.stringify(searchObj)}`
);
const url = `${appConfig.domain.mobileDomain}/pay/order_info?channel=wechat&type=WechatMP&order_no=${orderNo}&callback_url=${callbackUrl}`;
return url;
};
/**
* 开团
*/
handleCreateTeam = async () => {
const { groupId } = this.props;
const { rf } = this.urlParams;
// 本地开发环境没有openId, 所以不做判断
if (NODE_ENV !== 'development') {
if (!this.openId) {
message.error('未获取到授权的用户信息');
return;
}
}
monitor.log('', '立即开团');
// 开团
SpecialGroupService.createTeam(groupId, rf, this.openId)
.then(({ orderNo }) => {
if (orderNo) {
monitor.log('', '参团成功');
// 跳转订单支付页面
// 单独购买的链接不需要传teamId参数, 开团/参团的时候需要带上teamId参数
const payUrl = this.getPayUrl(orderNo);
window.location.href = payUrl;
} else {
message.error('订单号为空');
}
})
.catch((error) => {
monitor.log('', '开团失败!!! ' + error.msg || '接口发生错误');
switch (error.code) {
case CREATE_RESULT_CODE.LOGIN_REQUIRED: {
// 需要登录
this.setState({
modalKey: 'Login'
});
break;
}
case CREATE_RESULT_CODE.BIZ_GROUP_JOIN_LIMIT_SHEEPMOM: {
const errorMsg = `啊哦...您已参与过试听优惠活动,本次不能参团啦~`;
monitor.log('', `开团未成功:${errorMsg}`);
this.handleSetTipsText(errorMsg);
break;
}
case CREATE_RESULT_CODE.BIZ_GROUP_ACTIVITY_NOT_QUALIFIED: {
let errorMsg = '开团失败';
const { currentMemberConditionType } = error.data;
switch (currentMemberConditionType) {
case 2:
errorMsg = '您是非正式付费学员,本次不能开团哦~';
break;
case 3:
errorMsg = '您是付费学员,本次不能开团哦~';
break;
case 4:
errorMsg = '您已经参加过团购,本次不能开团啦~';
break;
case 5:
errorMsg = '您没有参加过团购,本次不能开团哦~';
break;
}
monitor.log('', `开团未成功:${errorMsg}`);
this.handleSetTipsText(errorMsg);
break;
}
default: {
message.error(error.msg || '发生错误了');
break;
}
}
});
};
/**
* 参团
*/
handleJoinTeam = async () => {
const { groupId, teamId } = this.props;
const { rf } = this.urlParams;
monitor.log('', '立即参团');
SpecialGroupService.joinTeam(groupId, teamId, rf, this.openId)
.then(({ orderNo }) => {
if (orderNo) {
monitor.log('', '参团成功');
// 跳转订单支付页面
// 单独购买的链接不需要传teamId参数, 开团/参团的时候需要带上teamId参数
const payUrl = this.getPayUrl(orderNo);
window.location.href = payUrl;
} else {
message.error('订单号为空');
}
})
.catch((error) => {
monitor.log('', '参团失败!!! ' + error.msg || '接口发生错误');
switch (error.code) {
case CREATE_RESULT_CODE.LOGIN_REQUIRED: {
// 需要登录
this.setState({
modalKey: 'Login'
});
break;
}
case CREATE_RESULT_CODE.BIZ_GROUP_JOIN_LIMIT_SHEEPMOM: {
const errorMsg = `啊哦...您已参与过试听优惠活动,本次不能参团啦~`;
monitor.log('', `开团未成功:${errorMsg}`);
this.handleSetTipsText(errorMsg);
break;
}
case CREATE_RESULT_CODE.BIZ_GROUP_ACTIVITY_NOT_QUALIFIED: {
let errorMsg = '参团失败';
const { currentMemberConditionType } = error.data;
switch (currentMemberConditionType) {
case 2:
errorMsg = '您是非正式付费学员,本次不能参团哦~';
break;
case 3:
errorMsg = '您是付费学员,本次不能参团哦~';
break;
case 4:
errorMsg = '您已经参加过团购,本次不能参团啦~';
break;
case 5:
errorMsg = '您没有参加过团购,本次不能参团哦~';
break;
}
monitor.log('', `参团未成功:${errorMsg}`);
this.handleSetTipsText(errorMsg);
break;
}
default: {
message.error(error.msg || '发生错误了');
break;
}
}
});
};
/**
* 单独购买
*/
handleSingleBuy = async () => {
const { groupId } = this.props;
const { rf } = this.urlParams;
monitor.log('', '单独购买');
// 单独购买
SpecialGroupService.singleBuy(groupId, rf, this.openId)
.then(({ orderNo }) => {
if (orderNo) {
monitor.log('', '单独购买成功');
// 跳转订单支付页面
// 单独购买的链接不需要传teamId参数, 开团/参团的时候需要带上teamId参数
const payUrl = this.getPayUrl(orderNo);
window.location.href = payUrl;
} else {
message.error('订单号为空');
}
})
.catch((error) => {
monitor.log('', '单独购买失败!!! ' + error.msg || '接口发生错误');
switch (error.code) {
case CREATE_RESULT_CODE.LOGIN_REQUIRED: {
// 需要登录
this.setState({
modalKey: 'Login'
});
break;
}
case CREATE_RESULT_CODE.BUSINESS_FAULT: {
this.handleSetTipsText(error.msg || '购买失败');
break;
}
default: {
message.error(error.msg || '发生错误了');
break;
}
}
});
};
handleHrefChange = (url) => {
return () => {
monitor.log('', '马上约课');
window.location.href = url;
};
};
handleSetTipsText = (text) => {
this.setState({
modalKey: SYSTEM_MODAL_KEY.NOT_JOIN_TIPS_MODAL,
tipsText: text
});
};
/**
* 团购活动未开始
* 活动倒计时
* @returns {*}
*/
renderNotBegin = () => {
return <div className={styles['button-normal']}>活动未开始,敬请期待哦~</div>;
};
/**
* 团购活动已结束
* 只显示马上约课
*/
renderEnd = () => {
return (
<div className={styles['button-normal']} onClick={this.handleHrefChange(bookingUrl)}>
马上约课
</div>
);
};
/**
* 没有开团/参团
* 1. 未登录==未参团
* 2. 登录未参团
* @returns {*}
*/
renderNotJoin = () => {
const {
singlePrice,
groupPrice,
teamId,
isFull,
allowFullJoin,
leaderCondition = [],
memberCondition
} = this.props;
const conditionArr = [];
if (leaderCondition.indexOf(JOINCONDITION.PAID_GREATER_1999) === -1) {
conditionArr.push('新生开团');
} else if (leaderCondition.indexOf(JOINCONDITION.PAID_LESS_1999) === -1) {
conditionArr.push('老生开团');
}
if (memberCondition.indexOf(JOINCONDITION.PAID_GREATER_1999) === -1) {
conditionArr.push('新生参团');
} else if (memberCondition.indexOf(JOINCONDITION.PAID_LESS_1999) === -1) {
conditionArr.push('老生参团');
}
// 1. 有teamId参数
// 2. 并且 ( 未满团 || 满团时允许参团 )
if (teamId && String(teamId) !== '-1' && (!isFull || allowFullJoin)) {
return (
<div className={styles['button-group']}>
<div className={styles['button-left']} onClick={this.handleSingleBuy}>
<span>{singlePrice ? '¥' + singlePrice : ''}</span>
<i>单独购买</i>
</div>
<div className={styles['button-right']} onClick={this.throttleJoinTeam}>
<span>{groupPrice ? '¥' + groupPrice : ''}</span>
<i>立即参团</i>
{conditionArr.length > 0 ? (
<div className={styles['button-condition']}>{`仅限${conditionArr.join(',')}`}</div>
) : null}
</div>
</div>
);
} else {
return (
<div className={styles['button-group']}>
<div className={styles['button-left']} onClick={this.handleSingleBuy}>
<span>{singlePrice ? '¥' + singlePrice : ''}</span>
<i>单独购买</i>
</div>
<div className={styles['button-right']} onClick={this.throttleCreateTeam}>
<span>{groupPrice ? '¥' + groupPrice : ''}</span>
<i>立即开团</i>
{conditionArr.length > 0 ? (
<div className={styles['button-condition']}>{`仅限${conditionArr.join(',')}`}</div>
) : null}
</div>
</div>
);
}
};
/**
* 显示我要当团长
* @returns {*}
*/
renderGroupLeader = () => {
const { teamId, isFull, allowFullJoin } = this.props;
// 1. 有teamId参数 并且不等于-1
// 2. 并且 ( 未满团 || 满团时允许参团 )
if (teamId && String(teamId) !== '-1' && (!isFull || allowFullJoin)) {
return (
<div className={styles['become-commander']} onClick={this.throttleCreateTeam}>
<div className={styles['button-commander']}>我要当团长</div>
</div>
);
}
return null;
};
/**
* 已经单独购买
* 马上约课, 分享给好友
*/
renderSingleBuy = () => {
const { spActivityType } = this.props;
return (
// 正常专题课团购展示马上约课,魔小兔产品不展约课按钮
spActivityType === SPECIAL_TYPE.NORMAL ? (
<div className={styles['button-group']}>
<div className={styles['button-left']} onClick={this.handleHrefChange(bookingUrl)}>
马上约课
</div>
<div className={styles['button-right']} onClick={this.handleOpenShareModal}>
分享给好友
</div>
</div>
) : (
<div className={styles['button-group']}>
<div className={styles['button-normal']} onClick={this.handleOpenShareModal}>
分享给好友
</div>
</div>
)
);
};
/**
* 已经开团/参团, 但是打开的不是自己的团
* 显示 查看我的团购
*/
renderOtherTeam = () => {
const { groupId, teamId } = this.props;
// 查看我的团购
const searchObj = {
groupId,
teamId,
rf: this.urlParams.rf || -1
};
const url = `${appConfig.basename}/special_group?${queryString.stringify(searchObj)}`;
return (
<div className={styles['button-normal']} onClick={this.handleHrefChange(url)}>
查看我的团购
</div>
);
};
/**
* 已经开团/参团, 包括(已经参团 没有teamId参数 或者有teamId参数并且等于自己的参加的团 )
* 马上约课, 邀请好友参团
*/
renderMyTeam = () => {
const { isFull, spActivityType } = this.props;
return (
// 正常专题课团购且团满或单独购买,展示马上约课,魔小兔产品不展约课按钮
isFull && spActivityType === SPECIAL_TYPE.NORMAL ? (
<div className={styles['button-group']}>
<div className={styles['button-left']} onClick={this.handleHrefChange(bookingUrl)}>
马上约课
</div>
<div className={styles['button-right']} onClick={this.handleOpenShareModal}>
邀请好友参团
</div>
</div>
) : (
<div className={styles['button-normal']} onClick={this.handleOpenShareModal}>
邀请好友参团
</div>
)
);
};
/**
* 登录/注册成功的回调
*/
handleLoginCallback = () => {
const { loadData, groupId, teamId } = this.props;
this.setState({
modalKey: ''
});
// 登录成功之后 重新获取团购数据
loadData(groupId, teamId);
};
/**
* 关闭modal
*/
handleHideModal = () => {
this.setState({
modalKey: ''
});
};
/**
* 打开客服弹窗
*/
handleOpenCustom = () => {
monitor.log('', '客服弹窗');
this.setState({
modalKey: SYSTEM_MODAL_KEY.CUSTOM_SERVICE_MODAL
});
};
/**
* 打开微信弹窗
*/
handleOpenWeiXinModal = () => {
monitor.log('', '打开微信公众号弹窗');
this.setState({
modalKey: SYSTEM_MODAL_KEY.WEIXIN_MODAL
});
};
/**
* 打开分享给好友弹窗
*/
handleOpenShareModal = () => {
monitor.log('', '打开分享给好友弹窗');
this.setState({
modalKey: SYSTEM_MODAL_KEY.SHARE_MODAL
});
};
/**
* 显示弹窗
* @returns {*}
*/
renderModal = () => {
const { modalKey, tipsText = '啊哦,你不能作为团员参加哦~' } = this.state;
// 团长Id
const { groupId, teamLeaderId } = this.props;
switch (modalKey) {
case 'Login': // 登录或者注册
return (
<ModalLogin
onOk={this.handleLoginCallback}
onCancel={this.handleHideModal}
promotion="group"
actType="GROUP_BUYING_SP"
actId={groupId}
teamLeaderId={teamLeaderId}
/>
);
case SYSTEM_MODAL_KEY.CUSTOM_SERVICE_MODAL: // 底部客服弹窗类型
return (
<CustomServiceModal
showTel={false}
onOpenWeiXinModal={this.handleOpenWeiXinModal}
onCancel={this.handleHideModal}
/>
);
case SYSTEM_MODAL_KEY.WEIXIN_MODAL: // 微信客服弹窗类型
return (
<WeiXinModal
onCancel={this.handleHideModal}
imageUrl={bonny}
header="关注魔小兔英语,随时咨询客服"
/>
);
case SYSTEM_MODAL_KEY.NOT_JOIN_TIPS_MODAL: // 不能参加团购弹窗提示
return <NoJoinTipsModal tipsText={tipsText} onOk={this.handleHideModal} />;
case SYSTEM_MODAL_KEY.GROUP_SUCCESS_MODAL: // 团购成功,引导关注公众号
return (
<WeiXinModal
header={
<div>
<p>恭喜您成功购买团购课程,</p>
<p>关注魔小兔英语服务号,赶紧约课吧!</p>
</div>
}
imageUrl={bonny}
onCancel={this.handleHideModal}
/>
);
case SYSTEM_MODAL_KEY.SHARE_MODAL: // 提示分享
return <ShareLayerModal onCancel={this.handleHideModal} />;
}
return null;
};
render() {
const {shareOptions} = this.state;
const {groupStatus, joinStatus, groupId, teamId, spActivityType, account} = this.props;
let element = null;
let groupLeaderElement = null;
// 活动状态未知
if (groupStatus === GROUP_STATUS.UNKNOWN) {
return null;
}
// 判断活动状态
if (groupStatus === GROUP_STATUS.NOT_BEGIN) {
// 活动未开始
element = this.renderNotBegin();
} else if (groupStatus === GROUP_STATUS.END) {
// 活动已结束
element = this.renderEnd();
} else {
// 活动进行中
switch (joinStatus) {
case JOIN_STATUS.NOT_JOIN: // 未登录 或者 没有开团/参团
element = this.renderNotJoin();
groupLeaderElement = this.renderGroupLeader();
break;
case JOIN_STATUS.SINGLE_BUY: // 已经单独购买
element = this.renderSingleBuy();
break;
case JOIN_STATUS.MY_TEAM: // 已经开团/参团, 包括(已经参团 没有teamId参数 或者有teamId参数并且等于自己的参加的团 )
element = this.renderMyTeam();
break;
case JOIN_STATUS.OTHER_TEAM: // 已经开团/参团, 但是打开的不是自己的团
element = this.renderOtherTeam();
break;
default:
element = this.renderEnd();
break;
}
}
return (
<div>
{(spActivityType === SPECIAL_TYPE.NORMAL || groupStatus !== GROUP_STATUS.END) && (
<div className={styles['footer']}>
<div className={styles['service']} onClick={this.handleOpenCustom}>
客服
</div>
{element}
</div>
)}
{groupLeaderElement}
{this.renderModal()}
<WechatConfig key={groupId + teamId} showShare={true} shareOptions={shareOptions} account={account}/>
</div>
);
}
}
export default withRouter(Footer);