Commit 68e66bf0 by zhanghaozhe

周年庆预热

parent 9787909a
...@@ -4,14 +4,13 @@ import { http } from "@/utils" ...@@ -4,14 +4,13 @@ import { http } from "@/utils"
import { Toast } from "antd-mobile"; import { Toast } from "antd-mobile";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { connect } from "react-redux"; import { connect } from "react-redux";
import './index.scss' import './index.scss'
import { Popup } from "@common/index"
class Anniversary2020 extends Component { class Anniversary2020 extends Component {
nav = null nav = null
defaultAvatar = 'https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/home/avatar_20191104.png'
stages = { stages = {
1: '基础', 1: '基础',
2: '进阶', 2: '进阶',
...@@ -19,6 +18,13 @@ class Anniversary2020 extends Component { ...@@ -19,6 +18,13 @@ class Anniversary2020 extends Component {
4: '拓展', 4: '拓展',
} }
stageParams = ['one', 'two', 'three', 'four'] stageParams = ['one', 'two', 'three', 'four']
records = null
answerRule = `
1.邀请好友加入队伍,好友答对题你和好友均可增加抽奖机会
2.每增加3个队员答对题,你可以增加N次抽奖机会,N=1 ,2, 3 (有3个队员答对题,你可+1次抽奖机会;6个队员答对题,你再+2次抽奖机会,超过6个队员答对题时,每+3人答对题都可+3次抽奖机会)
3.被邀请好友答对题TA可+1次抽奖机会
4.每人只能当1次队员哦
`
state = { state = {
navs: [ navs: [
...@@ -64,25 +70,33 @@ class Anniversary2020 extends Component { ...@@ -64,25 +70,33 @@ class Anniversary2020 extends Component {
stageCourses: [], stageCourses: [],
activityData: {}, activityData: {},
team: {}, team: {},
userAddress: {
name: '',
phone: '',
address: '',
},
isShowUserAddress: false,
prizeData: {},
prizeRecords: [],
prizeRecordsPagination: 0,
isShowPrizesRecords: false,
} }
componentDidMount() { componentDidMount() {
console.log(this.props.user)
this.getActivityStage() this.getActivityStage()
this.getTeam() this.getTeam()
Promise.all([ this.getUserAddress()
this.getAuditionCourses(), this.getPrizeData()
this.getGroupCourses(), this.getPrizeRecords()
this.getStageCourses('zero'), this.getAuditionCourses()
]) this.getGroupCourses()
.then(() => { this.getStageCourses('zero')
this.bindNavAction()
})
} }
componentDidUpdate(prevProps, prevState) { componentDidUpdate(prevProps, prevState) {
if (prevState.navActive !== this.state.navActive) { if (prevState.navActive !== this.state.navActive) {
this.showActiveNav()
} }
} }
...@@ -94,7 +108,7 @@ class Anniversary2020 extends Component { ...@@ -94,7 +108,7 @@ class Anniversary2020 extends Component {
if (code === 200) { if (code === 200) {
this.setState({ this.setState({
activityData: data, activityData: data,
}); }, this.bindNavAction);
} else { } else {
Toast.info(msg) Toast.info(msg)
} }
...@@ -108,7 +122,7 @@ class Anniversary2020 extends Component { ...@@ -108,7 +122,7 @@ class Anniversary2020 extends Component {
if (code === 200) { if (code === 200) {
this.setState({ this.setState({
auditions: data, auditions: data,
}); }, this.bindNavAction);
} else { } else {
Toast.info(msg) Toast.info(msg)
} }
...@@ -150,6 +164,20 @@ class Anniversary2020 extends Component { ...@@ -150,6 +164,20 @@ class Anniversary2020 extends Component {
stageCourses: state.stageCourses, stageCourses: state.stageCourses,
} }
} }
}, this.bindNavAction)
} else {
Toast.info(msg)
}
})
}
getPrizeData = () => {
http.get(`${API.home}/activity/anniversary/prize_data`)
.then(res => {
const {code, msg, data} = res.data
if (code === 200) {
this.setState({
prizeData: data,
}) })
} else { } else {
Toast.info(msg) Toast.info(msg)
...@@ -164,17 +192,92 @@ class Anniversary2020 extends Component { ...@@ -164,17 +192,92 @@ class Anniversary2020 extends Component {
if (code === 200) { if (code === 200) {
this.setState({ this.setState({
team: data, team: data,
}); }, this.bindNavAction);
} else { } else {
Toast.info(msg) Toast.info(msg)
} }
}) })
} }
getPrizeRecords = (() => {
let hasMore = true, isFetching = false
return () => {
if (isFetching || !hasMore) {
return
}
isFetching = true
http.get(`${API.home}/activity/anniversary/user_prizes/${this.state.prizeRecordsPagination}`)
.then(res => {
const {code, msg, data} = res.data
if (code === 200) {
if (isEmpty(data)) {
hasMore = false
}
const _records = Array.isArray(data) ? data : []
this.setState(state => {
return {
prizeRecords: [...state.prizeRecords, ..._records],
prizeRecordsPagination: state.prizeRecordsPagination + 1,
}
}, () => {
setTimeout(() => {
isFetching = false
}, 100)
});
} else {
Toast.info(msg)
}
})
}
})()
handleRecordsScroll = debounce((e) => {
let scrollTop = e.target.scrollTop, scrollHeight = e.target.scrollHeight, height = e.target.clientHeight
if (scrollTop > scrollHeight - height - 120) {
this.getPrizeRecords()
}
}, 16)
componentWillUnmount() { componentWillUnmount() {
document.removeEventListener('scroll', this.setNavActive) document.removeEventListener('scroll', this.setNavActive)
document.body.style.overflow = 'auto'
} }
handleChange = e => {
let name = e.target.name, value = e.target.value
this.setState(state => {
return {
userAddress: {...state.userAddress, ...{[name]: value}},
}
});
}
submitUserAddress = () => {
http.post(`${API.home}/sys/update_address`, this.state.userAddress)
.then(res => {
const {code, msg} = res.data
if (code === 200) {
Toast.info('提交成功')
this.setState({
isShowUserAddress: false,
});
} else {
Toast.info(msg)
}
})
}
getUserAddress = () => {
http.get(`${API.home}/sys/user_address_info`)
.then(res => {
const {code, msg, data} = res.data
if (code === 200) {
this.setState({
userAddress: data,
});
}
})
}
bindNavAction = () => { bindNavAction = () => {
document.removeEventListener('scroll', this.setNavActive) document.removeEventListener('scroll', this.setNavActive)
...@@ -216,9 +319,29 @@ class Anniversary2020 extends Component { ...@@ -216,9 +319,29 @@ class Anniversary2020 extends Component {
} }
} }
} }
}, 30) }, 1000 / 60)
showRule = (content) => {
this.popupInstance = Popup({
className: 'rule-popup',
title: '活动规则',
content,
})
}
showActiveNav = () => { showActiveNav = () => {
const listItems = this.nav.querySelectorAll('li')
const activeItem = listItems[this.state.navActive]
const box = activeItem.getBoundingClientRect()
let offsetWidth = this.nav.offsetWidth, scrollLeft = this.nav.scrollLeft
if (box.left < 0) {
this.nav.scrollLeft = box.left
} else if (box.right > offsetWidth + scrollLeft) {
this.nav.scrollLeft = box.right
}
}
draw = () => {
} }
...@@ -235,8 +358,13 @@ class Anniversary2020 extends Component { ...@@ -235,8 +358,13 @@ class Anniversary2020 extends Component {
stageCourses, stageCourses,
activityData, activityData,
team, team,
userAddress,
isShowUserAddress,
prizeData,
isShowPrizesRecords,
prizeRecords,
} = this.state } = this.state
const {user, history} = this.props const {history} = this.props
const _auditions = auditionShowAll && auditions.length ? auditions : auditions.slice(0, 4) const _auditions = auditionShowAll && auditions.length ? auditions : auditions.slice(0, 4)
const _group = groupShowAll && group.length ? group : group.slice(0, 4) const _group = groupShowAll && group.length ? group : group.slice(0, 4)
...@@ -251,7 +379,12 @@ class Anniversary2020 extends Component { ...@@ -251,7 +379,12 @@ class Anniversary2020 extends Component {
{ {
navs.map((item, index) => { navs.map((item, index) => {
return <li key={index} className={index === navActive ? 'active' : ''}> return <li key={index} className={index === navActive ? 'active' : ''}>
<a href={item.id}>{item.text}</a> <a href='javascript:void(0);' onClick={() => {
this.setState({
navActive: index,
});
window.scrollTo(0, this.state.sectionsPosition[index].top)
}}>{item.text}</a>
</li> </li>
}) })
} }
...@@ -326,7 +459,7 @@ class Anniversary2020 extends Component { ...@@ -326,7 +459,7 @@ class Anniversary2020 extends Component {
<div className="block-title" <div className="block-title"
style={{background: `url(${titleImages[1]}) no-repeat`, backgroundSize: 'contain'}}></div> style={{background: `url(${titleImages[1]}) no-repeat`, backgroundSize: 'contain'}}></div>
<div className="rule"> <div className="rule">
<a href="javascript:void(0);">规则</a> <a href="javascript:void(0);" onClick={this.showRule.bind(this, prizeData.rule)}>规则</a>
</div> </div>
<div className="prize-container"> <div className="prize-container">
<div className={'h-bar'}></div> <div className={'h-bar'}></div>
...@@ -336,15 +469,17 @@ class Anniversary2020 extends Component { ...@@ -336,15 +469,17 @@ class Anniversary2020 extends Component {
<ul className="prizes"> <ul className="prizes">
{ {
Array(9).fill('a').map((item, index) => { Array(9).fill('a').map((item, index) => {
return <li key={index}> return <li key={index}
className={index === 4 ? (prizeData.odd_times ? 'available' : 'unavailable') : ''}>
{ {
index !== 4 index !== 4
? <div className={'prize'}> ? <div className={'prize'}>
<img src="" alt=""/> <img src="" alt=""/>
</div> </div>
: <div className={'draw'}> : activityData.stage === 1 ?
<div className={'draw'} style={{lineHeight: '350%'}}>715日开始</div> : <div className={'draw'}>
<div>抽奖</div> <div>抽奖</div>
<div>剩余0次机会</div> <div>剩余{prizeData.odd_times || 0}次机会</div>
</div> </div>
} }
</li> </li>
...@@ -354,14 +489,31 @@ class Anniversary2020 extends Component { ...@@ -354,14 +489,31 @@ class Anniversary2020 extends Component {
</div> </div>
<div className="content"> <div className="content">
<div className={'operations'}> <div className={'operations'}>
<a href="javascript:void(0);">收货信息</a> <a href="javascript:void(0);" onClick={() => {
<a href="javascript:void(0);">中奖纪录</a> this.setState({
isShowUserAddress: true,
})
}}>收货信息</a>
<a href="javascript:void(0);" onClick={() => {
document.body.style.overflow = 'hidden'
this.setState({
isShowPrizesRecords: true,
}, () => {
this.records && this.records.addEventListener('scroll', this.handleRecordsScroll)
});
}}>中奖纪录</a>
</div> </div>
<div className="lottery-info"> <div className="lottery-info">
<div className={'title'}><i></i>如何获取更多抽奖机会?</div> <div className={'title'}><i></i>如何获取更多抽奖机会?</div>
<ul className={'rules'}> <ul className={'rules'}>
<li><span className={'index'}>1</span>每日签到可获得1次抽奖机会</li> {
<li><span className={'index'}>2</span>每日签到可获得1次抽奖机会</li> prizeData.more_rule && prizeData.more_rule.split('\n').map((item, index) => {
return <li key={index}>
<span className={'index'}>{index + 1}</span>
{item}
</li>
})
}
</ul> </ul>
</div> </div>
</div> </div>
...@@ -369,7 +521,8 @@ class Anniversary2020 extends Component { ...@@ -369,7 +521,8 @@ class Anniversary2020 extends Component {
<section id={'group-answer'} className={'group-answer block'}> <section id={'group-answer'} className={'group-answer block'}>
<div className="block-title" style={{background: `url(${titleImages[2]})`, backgroundSize: 'contain'}}></div> <div className="block-title" style={{background: `url(${titleImages[2]})`, backgroundSize: 'contain'}}></div>
<div style={{textAlign: 'center', marginBottom: '10px'}}> <div style={{textAlign: 'center', marginBottom: '10px'}}>
<a className="rule-btn" href="javascript:void(0);">规则</a> <a className="rule-btn" href="javascript:void(0);"
onClick={this.showRule.bind(this, this.answerRule)}>规则</a>
</div> </div>
<div className="content"> <div className="content">
<div className="team"> <div className="team">
...@@ -389,10 +542,15 @@ class Anniversary2020 extends Component { ...@@ -389,10 +542,15 @@ class Anniversary2020 extends Component {
</li> </li>
}) })
} }
<li className={'more'}>更多</li> {
activityData.stage !== 1 && <li className={'more'}>更多</li>
}
</ul> </ul>
<div className="invite"> <div className="invite">
<button className={'invite'}>邀请好友加入队伍</button> {
activityData.stage === 1 ? <button className={'invite'}>715日开始</button> :
<button className={'invite'}>邀请好友加入队伍</button>
}
</div> </div>
</div> </div>
<div className="des"> <div className="des">
...@@ -409,10 +567,18 @@ class Anniversary2020 extends Component { ...@@ -409,10 +567,18 @@ class Anniversary2020 extends Component {
</div> </div>
<div className="exercise"> <div className="exercise">
<div className="func"> <div className="func">
<div className="btn"> {
<button><i></i>开始练习</button> activityData.stage === 1
</div> ? <div className="btn">
<div className="chance">今日剩余<span>2</span>次</div> <button>715日开始</button>
</div>
: <>
<div className="btn">
<button><i></i>开始练习</button>
</div>
< div className="chance">今日剩余<span>{activityData.practice_num}</span>次</div>
</>
}
</div> </div>
<div className="des"> <div className="des">
<div className="title">练一练</div> <div className="title">练一练</div>
...@@ -425,44 +591,68 @@ class Anniversary2020 extends Component { ...@@ -425,44 +591,68 @@ class Anniversary2020 extends Component {
<div className="rank-list"> <div className="rank-list">
<div className="title">测试排行榜</div> <div className="title">测试排行榜</div>
<div className="description">仅展示前50名,队员越多、用时越短排名越靠前</div> <div className="description">仅展示前50名,队员越多、用时越短排名越靠前</div>
<div className="prize-des"> <div className="prize-display">
TOP1VIP年会员(3299元)+300元京东购物卡;<br/> <ul>
TOP2VIP年会员(3299元)+200元京东购物卡;<br/> <li className={'top-three'}>
TOP3VIP年会员(3299元);<br/> <img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active20_717/m/top1.png" alt=""/>
TOP4-6:【七月任一线上课】课程;<br/> </li>
TOP7-10:纸质书籍(统计学、西瓜书、百面机器学习任选1本)。 <li className={'top-three'}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active20_717/m/top2.png" alt=""/>
</li>
<li className={'top-three'}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active20_717/m/top3.png" alt=""/>
</li>
<li>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active20_717/m/top4%EF%BD%9E7.png"
alt=""/>
</li>
<li>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active20_717/m/top8%EF%BD%9E15.png"
alt=""/>
</li>
<li>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active20_717/m/top16%EF%BD%9E30.png"
alt=""/>
</li>
<li>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active20_717/m/top31%EF%BD%9E50.png"
alt=""/>
</li>
</ul>
</div> </div>
<table> {
<thead> prizeData.stage !== 1 && <table>
<tr> <thead>
<th>名次</th> <tr>
<th>队长</th> <th>名次</th>
<th>队员</th> <th>队长</th>
<th>奖品</th> <th>队员</th>
</tr> <th>奖品</th>
</thead> </tr>
<tbody> </thead>
{ <tbody>
Array(5).fill('a').map((item, index) => { {
return <tr key={index}> Array(5).fill('a').map((item, index) => {
<td> return <tr key={index}>
{ <td>
index < 3 ? <img src={rankIcons[index]} alt=""/> : index + 1 {
} index < 3 ? <img src={rankIcons[index]} alt=""/> : index + 1
</td> }
<td> </td>
<img <td>
src="https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/home/avatar_20191104.png" <img
alt="" className={'avatar'}/> src="https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/home/avatar_20191104.png"
限制宽度比例限制宽度比例 alt="" className={'avatar'}/>
</td> 限制宽度比例限制宽度比例
<td>723</td> </td>
<td>最多就显示这么多几个字吧</td> <td>723</td>
</tr> <td>最多就显示这么多几个字吧</td>
}) </tr>
} })
</tbody> }
</table> </tbody>
</table>
}
<div className="btn"> <div className="btn">
<button>查看更多</button> <button>查看更多</button>
</div> </div>
...@@ -567,7 +757,7 @@ class Anniversary2020 extends Component { ...@@ -567,7 +757,7 @@ class Anniversary2020 extends Component {
return <li className={'course'} key={index}> return <li className={'course'} key={index}>
<div className="cover"> <div className="cover">
{ {
item.save && <span>立省{item.save}</span> item.save && <span>立省{item.save}</span>
} }
<img src={item.image_name} <img src={item.image_name}
alt=""/> alt=""/>
...@@ -605,6 +795,67 @@ class Anniversary2020 extends Component { ...@@ -605,6 +795,67 @@ class Anniversary2020 extends Component {
} }
</div> </div>
</section> </section>
{
isShowUserAddress &&
<div className="modal-cover">
<div className="modal recipient">
<h4 className="title">收货信息</h4>
<div className="tip">获奖用户(以最终榜单为准)请及时填写收货信息</div>
<input type="text" name={'name'} value={userAddress.name} placeholder={'收件人'}
onChange={this.handleChange}/>
<input type="text" name={'phone'} value={userAddress.phone} placeholder={'联系方式'}
onChange={this.handleChange}/>
<input type="text" name={'address'} value={userAddress.address} placeholder={'收货地址'}
onChange={this.handleChange}/>
<button disabled={!userAddress.name || !userAddress.phone || !userAddress.address}
onClick={this.submitUserAddress}>提交
</button>
<i className={'iconfont iconiconfront-2 close'} onClick={() => {
this.setState({
isShowUserAddress: false,
})
}}></i>
</div>
</div>
}
{
isShowPrizesRecords && <div className={'modal-cover prize-records'}>
<div className="modal">
<h4 className="title">中奖纪录</h4>
<div className="content" ref={el => this.records = el}>
<div className="rule">
1. 现金红包自动发放到账户中,可前往 我的- 赚奖学金 中提现;<br/>
2. 代金券碎片自动发放到账户中,可前往优惠券 - 碎片合成 中兑换代金券;<br/>
3. 实物奖品请尽快填写收货信息,活动结束后统一邮寄。
</div>
<ul className={'records'}>
{
!!prizeRecords.length && prizeRecords.map((item, index) => {
return <li key={index}>
<div className="record">
<div className="name">
{item.prize_name} {(item.prize_type === 1 || item.prize_type === 2) && `${item.amount}元`}
</div>
<div className="time">{item.create_time}</div>
</div>
{
item.prize_type === 4 && <div className="contact">{item.prize_info}</div>
}
</li>
})
}
</ul>
<i className={'iconfont iconiconfront-2 close'} onClick={() => {
this.records.removeEventListener('scroll', this.handleRecordsScroll)
document.body.style.overflow = 'auto'
this.setState({
isShowPrizesRecords: false,
});
}}></i>
</div>
</div>
</div>
}
</div> </div>
); );
} }
......
...@@ -30,10 +30,10 @@ ...@@ -30,10 +30,10 @@
color: #fff; color: #fff;
font-size: 15px; font-size: 15px;
z-index: 100; z-index: 100;
overflow: auto;
ul { ul {
white-space: nowrap; white-space: nowrap;
overflow: auto;
} }
li { li {
...@@ -57,6 +57,16 @@ ...@@ -57,6 +57,16 @@
} }
.block { .block {
&:target {
&::before {
display: block;
content: " ";
margin-top: -75px; // Set the Appropriate Height
height: 75px; // Set the Appropriate Height
visibility: hidden;
}
}
&-title { &-title {
width: 150px; width: 150px;
height: 32px; height: 32px;
...@@ -291,8 +301,15 @@ ...@@ -291,8 +301,15 @@
} }
&:nth-child(5) { &:nth-child(5) {
background: url("./images/draw.png") no-repeat;
background-size: contain; background-size: contain;
&.available {
background: url("./images/lottery-button-available.png") no-repeat;
}
&.unavailable {
background: url("./images/draw.png") no-repeat !important;
}
} }
} }
...@@ -605,10 +622,31 @@ ...@@ -605,10 +622,31 @@
opacity: .8; opacity: .8;
} }
.prize-des { .prize-display {
padding: 0 8px; ul {
font-size: 13px; display: flex;
white-space: pre-wrap; flex-wrap: wrap;
justify-content: space-between;
}
li {
img {
width: 167px;
height: 80px;
}
}
.top-three {
img {
width: 110px;
height: 100px;
}
&:nth-child(3) {
margin-right: 0;
}
}
} }
.btn { .btn {
...@@ -804,4 +842,157 @@ ...@@ -804,4 +842,157 @@
vertical-align: middle; vertical-align: middle;
} }
} }
.modal-cover {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .6);
z-index: 200;
.modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
padding: 20px 25px;
background: #fff;
border-radius: 10px;
}
.close {
position: absolute;
bottom: -54px;
left: 50%;
transform: translateX(-50%);
font-size: 24px;
color: #fff;
}
.title {
font-size: 16px;
color: #525C65;
text-align: center;
margin-bottom: 6px;
}
.tip {
font-size: 13px;
color: #ED6A1D;
}
.recipient {
input {
width: 100%;
height: 40px;
line-height: 40px;
padding: 0 10px;
margin-top: 10px;
border: 1px solid #DDD;
font-size: 13px;
&:first-child {
margin-top: 15px;
}
&::placeholder {
color: #999;
}
}
button {
@include button;
width: 121px;
height: 33px;
transform: translateX(50%);
margin-top: 18px;
border-radius: 17px;
color: #fff;
font-size: 15px;
background: #09f;
&[disabled] {
background: rgba(84, 92, 100, .3);
}
}
}
}
}
.rule-popup {
.title {
font-size: 16px;
color: #525C65;
text-align: center;
margin-bottom: 6px;
}
.content {
font-size: 14px;
color: #525C65;
white-space: pre-line;
line-height: 21px;
}
}
.prize-records {
.modal {
padding-left: 15px !important;
padding-right: 15px !important;
}
.content {
max-height: 280px;
overflow: auto;
}
.rule {
font-size: 13px;
color: #ED6A1D;
white-space: pre-line;
}
.records {
li {
.record {
display: flex;
justify-content: space-between;
width: 270px;
height: 30px;
margin-top: 5px;
line-height: 30px;
background: rgba(255, 255, 255, 1);
border: 1px solid rgba(209, 219, 228, .4);
}
.name {
width: 140px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
color: #271BD3;
font-size: 12px;
}
.time {
color: #545C64;
font-size: 12px;
}
}
}
.contact {
width: 270px;
height: 15px;
line-height: 15px;
background: rgba(240, 240, 240, 1);
color: #333;
font-size: 12px;
text-align: center;
}
} }
\ 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