UNPKG

react-app-shell

Version:

react打包脚本和example, 这里的版本请忽略

374 lines (353 loc) 11.3 kB
// 功能方法>>>引用: 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'; @inject(({ 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 // 初始化方法 }; }) @observer @checkUserAuth({ 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} > 限时秒杀&nbsp;立即抢购 </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} /> </> ); } } }