Commit 68e66bf0 by zhanghaozhe

周年庆预热

parent 9787909a
......@@ -4,14 +4,13 @@ import { http } from "@/utils"
import { Toast } from "antd-mobile";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import './index.scss'
import { Popup } from "@common/index"
class Anniversary2020 extends Component {
nav = null
defaultAvatar = 'https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/home/avatar_20191104.png'
stages = {
1: '基础',
2: '进阶',
......@@ -19,6 +18,13 @@ class Anniversary2020 extends Component {
4: '拓展',
}
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 = {
navs: [
......@@ -64,25 +70,33 @@ class Anniversary2020 extends Component {
stageCourses: [],
activityData: {},
team: {},
userAddress: {
name: '',
phone: '',
address: '',
},
isShowUserAddress: false,
prizeData: {},
prizeRecords: [],
prizeRecordsPagination: 0,
isShowPrizesRecords: false,
}
componentDidMount() {
console.log(this.props.user)
this.getActivityStage()
this.getTeam()
Promise.all([
this.getAuditionCourses(),
this.getGroupCourses(),
this.getStageCourses('zero'),
])
.then(() => {
this.bindNavAction()
})
this.getUserAddress()
this.getPrizeData()
this.getPrizeRecords()
this.getAuditionCourses()
this.getGroupCourses()
this.getStageCourses('zero')
}
componentDidUpdate(prevProps, prevState) {
if (prevState.navActive !== this.state.navActive) {
this.showActiveNav()
}
}
......@@ -94,7 +108,7 @@ class Anniversary2020 extends Component {
if (code === 200) {
this.setState({
activityData: data,
});
}, this.bindNavAction);
} else {
Toast.info(msg)
}
......@@ -108,7 +122,7 @@ class Anniversary2020 extends Component {
if (code === 200) {
this.setState({
auditions: data,
});
}, this.bindNavAction);
} else {
Toast.info(msg)
}
......@@ -150,6 +164,20 @@ class Anniversary2020 extends Component {
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 {
Toast.info(msg)
......@@ -164,17 +192,92 @@ class Anniversary2020 extends Component {
if (code === 200) {
this.setState({
team: data,
});
}, this.bindNavAction);
} else {
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() {
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 = () => {
document.removeEventListener('scroll', this.setNavActive)
......@@ -216,9 +319,29 @@ class Anniversary2020 extends Component {
}
}
}
}, 30)
}, 1000 / 60)
showRule = (content) => {
this.popupInstance = Popup({
className: 'rule-popup',
title: '活动规则',
content,
})
}
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 {
stageCourses,
activityData,
team,
userAddress,
isShowUserAddress,
prizeData,
isShowPrizesRecords,
prizeRecords,
} = this.state
const {user, history} = this.props
const {history} = this.props
const _auditions = auditionShowAll && auditions.length ? auditions : auditions.slice(0, 4)
const _group = groupShowAll && group.length ? group : group.slice(0, 4)
......@@ -251,7 +379,12 @@ class Anniversary2020 extends Component {
{
navs.map((item, index) => {
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>
})
}
......@@ -326,7 +459,7 @@ class Anniversary2020 extends Component {
<div className="block-title"
style={{background: `url(${titleImages[1]}) no-repeat`, backgroundSize: 'contain'}}></div>
<div className="rule">
<a href="javascript:void(0);">规则</a>
<a href="javascript:void(0);" onClick={this.showRule.bind(this, prizeData.rule)}>规则</a>
</div>
<div className="prize-container">
<div className={'h-bar'}></div>
......@@ -336,15 +469,17 @@ class Anniversary2020 extends Component {
<ul className="prizes">
{
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
? <div className={'prize'}>
<img src="" alt=""/>
</div>
: <div className={'draw'}>
: activityData.stage === 1 ?
<div className={'draw'} style={{lineHeight: '350%'}}>715日开始</div> : <div className={'draw'}>
<div>抽奖</div>
<div>剩余0次机会</div>
<div>剩余{prizeData.odd_times || 0}次机会</div>
</div>
}
</li>
......@@ -354,14 +489,31 @@ class Anniversary2020 extends Component {
</div>
<div className="content">
<div className={'operations'}>
<a href="javascript:void(0);">收货信息</a>
<a href="javascript:void(0);">中奖纪录</a>
<a href="javascript:void(0);" onClick={() => {
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 className="lottery-info">
<div className={'title'}><i></i>如何获取更多抽奖机会?</div>
<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>
</div>
</div>
......@@ -369,7 +521,8 @@ class Anniversary2020 extends Component {
<section id={'group-answer'} className={'group-answer block'}>
<div className="block-title" style={{background: `url(${titleImages[2]})`, backgroundSize: 'contain'}}></div>
<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 className="content">
<div className="team">
......@@ -389,10 +542,15 @@ class Anniversary2020 extends Component {
</li>
})
}
<li className={'more'}>更多</li>
{
activityData.stage !== 1 && <li className={'more'}>更多</li>
}
</ul>
<div className="invite">
<button className={'invite'}>邀请好友加入队伍</button>
{
activityData.stage === 1 ? <button className={'invite'}>715日开始</button> :
<button className={'invite'}>邀请好友加入队伍</button>
}
</div>
</div>
<div className="des">
......@@ -409,10 +567,18 @@ class Anniversary2020 extends Component {
</div>
<div className="exercise">
<div className="func">
<div className="btn">
<button><i></i>开始练习</button>
</div>
<div className="chance">今日剩余<span>2</span>次</div>
{
activityData.stage === 1
? <div className="btn">
<button>715日开始</button>
</div>
: <>
<div className="btn">
<button><i></i>开始练习</button>
</div>
< div className="chance">今日剩余<span>{activityData.practice_num}</span>次</div>
</>
}
</div>
<div className="des">
<div className="title">练一练</div>
......@@ -425,44 +591,68 @@ class Anniversary2020 extends Component {
<div className="rank-list">
<div className="title">测试排行榜</div>
<div className="description">仅展示前50名,队员越多、用时越短排名越靠前</div>
<div className="prize-des">
TOP1VIP年会员(3299元)+300元京东购物卡;<br/>
TOP2VIP年会员(3299元)+200元京东购物卡;<br/>
TOP3VIP年会员(3299元);<br/>
TOP4-6:【七月任一线上课】课程;<br/>
TOP7-10:纸质书籍(统计学、西瓜书、百面机器学习任选1本)。
<div className="prize-display">
<ul>
<li className={'top-three'}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active20_717/m/top1.png" alt=""/>
</li>
<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>
<table>
<thead>
<tr>
<th>名次</th>
<th>队长</th>
<th>队员</th>
<th>奖品</th>
</tr>
</thead>
<tbody>
{
Array(5).fill('a').map((item, index) => {
return <tr key={index}>
<td>
{
index < 3 ? <img src={rankIcons[index]} alt=""/> : index + 1
}
</td>
<td>
<img
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>
</tr>
})
}
</tbody>
</table>
{
prizeData.stage !== 1 && <table>
<thead>
<tr>
<th>名次</th>
<th>队长</th>
<th>队员</th>
<th>奖品</th>
</tr>
</thead>
<tbody>
{
Array(5).fill('a').map((item, index) => {
return <tr key={index}>
<td>
{
index < 3 ? <img src={rankIcons[index]} alt=""/> : index + 1
}
</td>
<td>
<img
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>
</tr>
})
}
</tbody>
</table>
}
<div className="btn">
<button>查看更多</button>
</div>
......@@ -567,7 +757,7 @@ class Anniversary2020 extends Component {
return <li className={'course'} key={index}>
<div className="cover">
{
item.save && <span>立省{item.save}</span>
item.save && <span>立省{item.save}</span>
}
<img src={item.image_name}
alt=""/>
......@@ -605,6 +795,67 @@ class Anniversary2020 extends Component {
}
</div>
</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>
);
}
......
......@@ -30,10 +30,10 @@
color: #fff;
font-size: 15px;
z-index: 100;
overflow: auto;
ul {
white-space: nowrap;
overflow: auto;
}
li {
......@@ -57,6 +57,16 @@
}
.block {
&:target {
&::before {
display: block;
content: " ";
margin-top: -75px; // Set the Appropriate Height
height: 75px; // Set the Appropriate Height
visibility: hidden;
}
}
&-title {
width: 150px;
height: 32px;
......@@ -291,8 +301,15 @@
}
&:nth-child(5) {
background: url("./images/draw.png") no-repeat;
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 @@
opacity: .8;
}
.prize-des {
padding: 0 8px;
font-size: 13px;
white-space: pre-wrap;
.prize-display {
ul {
display: flex;
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 {
......@@ -804,4 +842,157 @@
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