import React, { Component } from 'react' import QRCode from 'qrcode' import { http, SendMessageToApp, wxShare, is_weixin, getParam } from '@/utils' import { Link } from 'react-router-dom' import { throttle, findIndex, debounce } from 'lodash' import RulePopup from './rulePopup/index' import CoursePopup from './coursePopup/index' import RecordPopup from './recordPopup/index' import CourseList from './courseList/index' import SharePopup from './sharePopup/index' import LuckDraw from './luckDraw/index' import CollectBlessing from './collectBlessing/index' import ReserveCourse from './ReserveCourse/index' import ListHeader from './listHeader/index' import LevelTest from './levelTest/index' import RankList from './rankList/index' import './index.scss' import { Popup } from '@/common' import { Toast } from "antd-mobile" import Live from './live' import Banner from './banner' import cookie from "js-cookie" import { setCurrentUser, startFetchUser } from "@/store/userAction" import { addDays } from "date-fns" import { compose } from "redux" import { connect } from "react-redux" import FormalDraw from "./formal-draw" class BlessingPreheat extends Component { recordInstance = null constructor(props) { super(props) this.navTop = 183 this.prevY = 0 this.state = { userInfoList: [], // userInfoList: [{ // token:'fcfef221e60ab7a2-92a80d5d30196999', // uid:'545292', // uname:'xzhtest2', // avatar_file:'' // }], isRule: false, isCourse: false, inviteUrl: '', inviteVisible: false, joinLotteryVisible: false, timelineShareVisible: false, showRecordList: false, isFormal: false, // 1正式 0 预热 onlyShow: false, // 14号返场 isServer: false, serverUrl: '', shareMark: false, userInfo: {}, isSign: false, navs: [ { text: '积福气', id: 'lucky-value' }, { text: '幸运大抽奖', id: 'lucky-draw' }, { text: '预付定金', id: 'deposit' }, { text: '精品特惠', id: 'best-courses' }, { text: 'AI测试', id: 'ai-test' }, { text: '大咖直播', id: 'live' }, ], formalNavs: [ { text: '幸运大抽奖', id: 'lucky-draw' }, { text: '积福气', id: 'lucky-value' }, { text: '精品特惠', id: 'best-courses' }, { text: 'AI测试', id: 'ai-test' }, { text: '大咖直播', id: 'live' }, ], encoreNavs: [ { text: '精品特惠', id: 'best-courses' }, { text: '大咖直播', id: 'live' }, { text: '幸运大抽奖', id: 'lucky-draw' }, { text: '积福气', id: 'lucky-value' }, { text: 'AI测试', id: 'ai-test' }, ], index: 0, userHasError: props.user.hasError, isApp: false, isClose: false, testSum: 0, address: { name: '', phone: '', address: '' }, addressPopupVisible: false } } componentDidMount() { const _this = this; this.fetchUserBlessing() // setTimeout(function(){ // // 这里有获取ID的步骤,由于运营过多的调整,导致顺序不定,所以包含ID的title必须要放到判断中(防止出现多个title),设置定时器是因为如果返回较慢 获取不到ID导致报错 // _this.setInitialNavActiveStatus() // }, 50); // window.addEventListener('scroll', throttle(this.calcNavActive, 100)) if (is_weixin()) { wxShare({ title: 'AI充电节,积福气享1折秒课,超10万元奖品来就送!!', desc: '把这门超5万人报名的【Python基础入门 升级版】课程送给你,附200元红包,请笑纳!--七月在线', link: window.location.href, imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/index-share-img.png', }) } // 获取App登录信息 window['loginInfo'] = result => { this.loginInfo(result) } window['getNewData'] = result => { this.fetchUserBlessing() } window['QQWXWBshare'] = result => { http.post(`${API.home}/sys/add/blessing`, { share_platform: result, // 1 朋友圈 2 微博 3 qq type: 3 // 1:签到;3:分享;4:浏览课程; }).then(res => { const {code} = res.data if (code === 200) { Toast.info('+2点福气值~', 2, null, false) this.fetchUserBlessing() } }) } } componentWillUpdate() { const {isFormal,onlyShow} = this.state; if(isFormal === 1) { document.title = `11.11-11.13 AI充电节,为AI出击!重磅好课1折秒,海量奖品来就送-七月在线` if(onlyShow) { document.title = `11.14 AI充电节 返场钜惠!200本纸质书送完即止!` } }else{ document.title = `11.11-11.13 AI充电节,预热来袭!积福气享1折秒课,海量奖品来就送-七月在线` } } // 获取app登录数据 loginInfo = (result) => { this.setState({ userInfoList: result }, () => { if (this.state.userInfoList.length) { this.props.startFetchUser() this.appLogin() } }) } // 保存cookie appLogin = () => { let expires = addDays(new Date(), 90) this.state.userInfoList.map((item, index) => { cookie.set("token", item.token, {expires, path: '/', domain: '.julyedu.com'}) cookie.set("plat", item.plat, {expires, path: '/', domain: '.julyedu.com'}) cookie.set("uid", item.uid, {expires, path: '/', domain: '.julyedu.com'}) cookie.set("uname", item.uname, {expires, path: '/', domain: '.julyedu.com'}) cookie.set("avatar_file", item.avatar_file, {expires, path: '/', domain: '.julyedu.com'}) }) if (cookie.get("token") && cookie.get("uid")) { this.fetchUserBlessing() this.setState({ isApp: true }) } this.props.setCurrentUser(this.transformUser(this.state.userInfoList)) } transformUser = res => { let payload res.map((item, index) => { payload = { hasError: false, data: { username: item.uname, avatar: item.avatar_file, token: item.token, uid: item.uid }, isFetching: false } }) return payload } getActiveIndex = (arr, n) => { for (let i = 0, len = arr.length; i < len; i++) { if (arr[i] > n) { if (!i) { return i } else { if (Math.abs(n - arr[i]) < Math.abs(n - arr[i - 1])) { return i } else { return i - 1 } } } } } fetchMoudleId = (str) => { const {navs} = this.state return findIndex(navs, item => item.id === str) } componentWillUnmount () { window.removeEventListener('scroll', this.calcNavActive); } setInitialNavActiveStatus = () => { const observer = new MutationObserver(debounce((list, observer) => { const navs = this.state.navs.map(item => document.querySelector(`#${item.id}`)) if (navs.every(item => item)) { const navsTop = navs.map(item => item.offsetTop) const index = this.getActiveIndex(navsTop, window.pageYOffset) this.setState({index, navsTop}, () => { this.calcNavActive() observer.disconnect() }) } }, 30)) observer.observe(document.querySelector('#blessing-preheat'), {childList: true, subtree: true}) } initNav = (isFormal) => { const {formalNavs, onlyShow, encoreNavs} = this.state if (isFormal) { if(onlyShow) { this.setState({ navs: encoreNavs }, () => { this.setInitialNavActiveStatus() window.addEventListener('scroll', throttle(this.calcNavActive, 100)) }) } else { this.setState({ navs: formalNavs }, () => { this.setInitialNavActiveStatus() window.addEventListener('scroll', throttle(this.calcNavActive, 100)) }) } } } fetchMoudleId = (str) => { const {navs} = this.state return findIndex(navs, item => item.id === str) } fetchUserBlessing = () => { const {userInfo} = this.state const {history} = this.props; http.get(`${API.home}/sys/user/blessing`).then(res => { const {code, data} = res.data if (code === 200) { if(data.is_over) { if(!getParam('version')) { history.push('/'); } else { SendMessageToApp("toQualityCourse"); } } this.setState(()=>({ isSign: !!data.today_signed, isFormal: data.is_activity, onlyShow: data.onlyShow, testSum: parseInt(data.user_test_total, 10) || 0, userInfo: Object.assign({}, userInfo, { isFollow: data.subscribed, blessingVal: data.user_blessing_value, buyBlessing: (data.types_total_blessing_value && data.types_total_blessing_value.buy_course) ? data.types_total_blessing_value.buy_course : 0, inviteBlessing: (data.types_total_blessing_value && data.types_total_blessing_value.invite) ? data.types_total_blessing_value.invite : 0, }) })); if (data.is_login === 1) { this.handleToSign() } this.initNav(data.is_activity) } }) } handleToAddBlessing = (key) => { http.post(`${API.home}/sys/add/blessing`, { share_platform: key, // 1 朋友圈 2 微博 3 qq type: 3 // 1:签到;3:分享;4:浏览课程; }).then(res => { const {code} = res.data if (code === 200) { Toast.info('+2点福气值~', 2, null, false) } }) } handleToSign = () => { const {userInfo} = this.state http.post(`${API.home}/sys/add/blessing`, { type: 1 // 1:签到;3:分享;4:浏览课程; }).then(res => { const {code} = res.data if (code === 200) { this.setState({ isSign: true, userInfo: Object.assign({}, userInfo, { blessingVal: userInfo.blessingVal + 5 }) }) Toast.info('+5点福气值~', 2, null, false) } }) } handleToHide = (key) => { let obj = {} obj[key] = false this.setState({ ...obj }) } handleToShow = (key, isLogin = false) => { // 需要用户登录 并且用户未登录 const isLoginnew = !this.props.user.hasError if (isLogin && !isLoginnew) { this.toLogin() } else { if (key === 'shareMark') { this.setState({ isClose: false }) setTimeout(() => { this.setState({ isClose: true }) }, 5000) } let obj = {} obj[key] = true this.setState({ ...obj }) } } handleToShowNotice = () => { http.get(`${API['base-api']}/sys/activity/create_blessing_qrcode`).then(res => { const {errno, data, msg} = res.data if (errno === 200) { QRCode.toDataURL(data.url, { width: 120, height: 120, margin: 1 }).then(url => { Popup({ title: '扫码关注“七月在线”服务号', content: <img src={url} alt="barcode" className="qr-code"/>, className: 'invite-popup' }) }) .catch(err => { console.error(err) }) } else if (errno === 4030 || errno === 4040) { this.toLogin() } else { Toast.info(msg, 2, null, false) } }) } toLogin = () => { const {history} = this.props if (!getParam('version')) { history.push('/passport') } else { SendMessageToApp("toLogin") } } onCopy = () => { Toast.info('复制成功', 2, null, false) } toSection = (i, e) => { const {navs} = this.state e.preventDefault() let top = document.querySelector(`#${navs[i].id}`).offsetTop this.setState({ index: i }) window.scrollTo({ top: top - 60, left: 0 }) } calcNavActive = () => { const {navs, index} = this.state const y = window.scrollY let swipeDirection = y > this.prevY ? 'up' : 'down' let _index if (swipeDirection === 'up') { if(Number.isInteger(index)){ _index = (index + 1) >= navs.length ? index : index + 1 }else { _index = 0 } } else { if(Number.isInteger(index)){ _index = (index - 1) <= 0 ? 0 : index - 1 }else { _index = 0 } } let el = document.querySelector(`#${navs[_index].id}`) let nav = document.querySelector('#main-nav') if (el) { let top = el.offsetTop if (y <= this.navTop) { nav.classList.remove('fixed') } else { !nav.classList.contains('fixed') && nav.classList.add('fixed') } if (swipeDirection === 'up') { if (y + 30 + 30 >= top) { this.setState({ index: _index }) } } else { if (y + 30 + 20 <= top) { this.setState({ index: _index }) } } this.prevY = y } } getMyPrizeRecord = () => { const isLoginnew = !this.props.user.hasError const {history} = this.props if (!isLoginnew) { history.push('/passport') }else{ http.get(`${API.home}/sys/activity/my_lotteries`) .then(res => { const {code, data, msg} = res.data if (code == 200) { this.recordInstance = Popup({ title: '我的中奖纪录', className: 'prize-record-popup', content: ( <div className={'record-container'}> <div className="list-title"> <div>时间</div> <div>奖品名称</div> </div> <ul> { Array.isArray(data) ? data.map((item, index) => { return ( <li key={index}> <div className="time">{item.time}</div> <div className="name" onClick={this.showAddressPopup.bind(this, item['is_virtual'], item.prize)}>{item.prize}</div> </li> ) }) : <li style={{justifyContent: 'center'}}>暂无中奖纪录</li> } </ul> </div> ) }) } else { Toast.info(msg, 2, null, false) } }) } } submitAddress = debounce(() => { http.post(`${API.home}/sys/collect_info`, { ...this.state.address }) .then(res => { const {data, code, msg} = res.data if (code == 200) { this.setState({ addressPopupVisible: false }) } else { Toast.info(msg, 2, null, false) } }) }, 500) setAddressState = e => { const value = e.target.value const name = e.target.name this.setState({ address: { ...this.state.address, ...{ [name]: value } } }) } showAddressPopup = (isVirtual, prize) => { if (isVirtual) { Toast.info(`恭喜你抽中${prize},奖品已存放到你的账户`, 2, null, false) return } http.get(`${API.home}/sys/user_address_info`) .then(res => { const {data, code, msg} = res.data if (code == 200) { this.recordInstance && this.recordInstance.close() this.setState({ address: { ...this.state.address, ...{ name: data.name, phone: Number(data.phone), address: data.address } }, addressPopupVisible: true }) } else { Toast.info(msg, 2, null, false) } }) } render() { const { navs, userInfo, isRule, isCourse, isFormal, isSign, showRecordList, shareMark, index, isApp, isClose, testSum, address, addressPopupVisible, onlyShow, } = this.state const {history} = this.props const isLogin = !this.props.user.hasError return ( <div id={'blessing-preheat'}> <Banner isFormal={isFormal} navs={navs} toSection={this.toSection} index={index} onlyShow={onlyShow} /> {/* 精品课程特惠专区--返场 */} { onlyShow && ( <> <ListHeader id={'best-courses'} text="精品课程特惠专区" styles={{margin: '60px 0 15px'}}/> <CourseList isApp={isApp} isFormal={isFormal} isLogin={isLogin} history={this.props.history} toLogin={this.toLogin} /> </> ) } {/* 大咖直播--返场 */} { onlyShow && <Live isFormal={isFormal} isLogin={isLogin}/> } {/* 抽奖--正式 */} { isFormal === 1 && <> <ListHeader id={'lucky-draw'} text="幸运大抽奖" styles={{margin: onlyShow ? '30px 0 10px' : '60px 0 10px'}}/> { onlyShow ? ( <p className='active_over'>活动已结束</p> ) : null } <div className="formal-draw-btns"> <button className="luck-draw__button" onClick={() => this.handleToShow('isRule')}>活动规则></button> <button className='prize-record' onClick={this.getMyPrizeRecord}>中奖记录></button> </div> <FormalDraw toLogin={this.toLogin} isApp={isApp}/> </> } {/* 积福气 */} <ListHeader id={'lucky-value'} text="积福气,享受更多福利" styles={{margin: '30px 0 15px'}}/> { onlyShow ? ( <p className='active_over'>活动已结束</p> ) : null } <Link className="blessing__sort" to="/blessingRank"></Link> <CollectBlessing isSign={isSign} userInfo={userInfo} isLogin={isLogin} history={this.props.history} toSection={(e) => this.toSection(this.fetchMoudleId('best-courses'), e)} handleToShowList={() => this.handleToShow('isCourse')} handleToShowNotice={this.handleToShowNotice} toLogin={this.toLogin} handleToShowShare={() => this.handleToShow('shareMark')} /> {/* 幸运大抽奖--预热 */} { isFormal === 0 && <> <ListHeader id={'lucky-draw'} text="幸运大抽奖" styles={{margin: '30px 0 10px'}}/> <p className="luck-draw__tip">- 将于11月11日10点开启 -</p> <button className="luck-draw__button" onClick={() => this.handleToShow('isRule')}>活动规则></button> <LuckDraw/> </> } {/*定金--只在预热期间显示*/} { isFormal === 0 && <> <ListHeader id={'deposit'} text="预付1元定金,最高可省100元" styles={{margin: '30px 0 15px'}}/> <ReserveCourse isApp={isApp}/> </> } {/* 精品课程特惠专区 */} { !onlyShow && ( <> <ListHeader id={'best-courses'} text="精品课程特惠专区" styles={{margin: '30px 0 15px'}}/> <CourseList isApp={isApp} isFormal={isFormal} isLogin={isLogin} history={this.props.history} toLogin={this.toLogin} /> </> ) } { isRule && <RulePopup handleToHide={() => this.handleToHide('isRule')}/> } { isCourse && <CoursePopup toLogin={this.toLogin} history={history} isLogin={isLogin} handleToHide={() => this.handleToHide('isCourse')}/> } { showRecordList && <RecordPopup history={this.props.history} handleToHide={() => this.handleToHide('showRecordList')} /> } { shareMark && <SharePopup isClose={isClose} toClose={() => this.handleToHide('shareMark')}/> } <ListHeader id={'ai-test'} text="全国AI工程师水平测试" styles={{margin: '30px 0 15px'}}/> { onlyShow ? ( <p className='active_over'>活动已结束</p> ) : null } <div className="test__record" onClick={() => this.handleToShow('showRecordList', true)}> 测试记录> </div> <LevelTest history={history} testSum={testSum} isLogin={isLogin} toLogin={this.toLogin} /> <RankList></RankList> {/* 大咖直播 -- 正式活动 */} { !onlyShow && <Live isFormal={isFormal} isLogin={isLogin}/> } { addressPopupVisible && <div className="address-mask"> <div className="address-popup"> <div className="title">收货信息</div> <div className="address-info-container"> <div className="tip">请及时填写收货信息,获得实物奖品后将第一时间为您邮寄</div> <input type="text" placeholder={'收件人'} name={'name'} onChange={e => { this.setAddressState(e) }} value={address.name} /> <input type="tel" placeholder={'联系方式'} name={'phone'} onChange={e => { this.setAddressState(e) }} value={address.phone} /> <input type="text" placeholder={'收货地址'} name={'address'} onChange={e => { this.setAddressState(e) }} value={address.address} /> <button type='button' className={(address.name != '' && address.phone != '' && address.address != '') ? 'active' : ''} onClick={this.submitAddress} >提交 </button> <i className={'iconfont iconiconfront-2'} onClick={() => { this.setState({ addressPopupVisible: false }) }}/> </div> </div> </div> } </div> ) } } export default compose( connect( state => ({user: state.user}), {setCurrentUser, startFetchUser} ) )(BlessingPreheat)