Commit 85042f47 by FE

Merge branch '00' of gitlab.julyedu.com:baiguangyao/mr-julyedu into 00

parents 4976342b ca33604a
......@@ -14154,9 +14154,9 @@
}
},
"swiper": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-4.5.0.tgz",
"integrity": "sha512-jRCd/CGet9kaHwthHdd/sL/YU8CI157PWLyItnIcn/o/jP4haVky3zTF6f9F3JDpmQIw7jdWihISiYx0/oTHsg==",
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-4.5.1.tgz",
"integrity": "sha512-se6I7PWWu950NAMXXT+ENtF/6SVb8mPyO+bTfNxbQBILSeLqsYp3Ndap+YOA0EczOIUlea274PKejT6gKZDseA==",
"requires": {
"dom7": "^2.1.3",
"ssr-window": "^1.0.1"
......
......@@ -77,7 +77,7 @@
"sass-resources-loader": "^2.0.0",
"socket.io": "^2.2.0",
"style-loader": "0.23.1",
"swiper": "^4.5.0",
"swiper": "^4.5.1",
"terser-webpack-plugin": "1.2.2",
"url-loader": "1.1.2",
"video.js": "^7.6.5",
......
......@@ -3,7 +3,7 @@ import Routes from './router'
import cookie from 'js-cookie'
import { connect } from "react-redux"
import { setCurrentUser, startFetchUser } from "@/store/userAction"
import { withRouter } from 'react-router-dom'
import { withRouter, Link } from 'react-router-dom'
import { compose } from 'redux'
import { getParam, http, browser } from "@/utils"
import { Toast } from "antd-mobile"
......@@ -262,7 +262,12 @@ class App extends Component {
}
render() {
return <Routes/>
return <>
<Routes/>
<Link className={'year19-index'} to="/year/yearindex">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/gift-package.png" alt=""/>
</Link>
</>
}
}
......
......@@ -512,3 +512,18 @@ input[type="radio"]:checked:before {
color: #333;
font-size: 15px;
}
.year19-index {
display: block;
width: 58px;
height: 70px;
position: fixed;
top: 50%;
right: 0;
margin-top: -35px;
z-index: 9;
img {
width: 100%;
height: 100%;
}
}
\ No newline at end of file
......@@ -10,10 +10,16 @@ function ClosablePopup({
content,
className,
closable = true,
close = function () {},
close = function () {
},
clickMaskClose = true,
closeIcon = 'iconiconfront-2'
} = {}) {
closeIcon = 'iconiconfront-2',
afterClose = function () {
},
remove = function () {
}
} = {}) {
function unmountComponent() {
......@@ -28,9 +34,11 @@ function ClosablePopup({
if (_c && _c.then) {
_c.then(() => {
unmountComponent()
afterClose()
})
} else {
unmountComponent()
afterClose()
}
}
......@@ -51,15 +59,14 @@ function ClosablePopup({
<div className="content">
{content}
</div>
</div>
{
closable &&
(re.test(closeIcon)
? <img src={closeIcon} alt="" className={'close-icon'} onClick={_close} />
: <i className={`close iconfont ${closeIcon}`} onClick={_close} />
)
? <img src={closeIcon} alt="" className={'close-icon'} onClick={_close}/>
: <i className={`close iconfont ${closeIcon}`} onClick={_close}/>)
}
</div>
</div>
)
const div = document.createElement('div')
document.body.appendChild(div)
......@@ -68,7 +75,8 @@ function ClosablePopup({
ReactDOM.render(closablePopup, div)
return {
close: _close
close: _close,
remove: unmountComponent
}
}
......
......@@ -740,6 +740,10 @@
// //}
}
.index-box + .nav-bar + .year19-index{
display: none;
}
.borderTop {
width: 100%;
height: 8px;
......
import React, { Component } from 'react'
import { http } from "@/utils"
import './prizes.scss'
import { Popup } from "@common/index"
import Loadable from '@loadable/component'
const SystemBulletScreen = Loadable(() => import(/* webpackChunkName: 'system-notices' */'@components/activity/newyear-2019/common/system-bullet-screen'))
class Prizes extends Component {
prizeBox
prizeList
bg
innerBox
state = {
prizes: [],
notices: [],
rule: [],
unfoldList: false,
}
componentDidMount() {
this.getPrizes()
}
getPrizes = () => {
http.get(`${API.home}/sys/prize_data`)
.then(res => {
const {code, data, msg} = res.data
if (code == 200) {
this.setState({
prizes: data['prize_data'],
notices: data['notices'],
rule: data['rule']
})
} else {
Toast.info(msg, 2, null, false)
}
})
}
showRules = () => {
Popup({
title: '组队开宝箱活动规则',
className: 'landing-treasure-rules',
content: this.state.rule,
closeIcon: this.closeIcon
})
}
showMore = () => {
this.setState(prev => {
if (this.state.unfoldList) {
this.bg.style = this.innerBox.style = this.prizeBox.style = ''
} else {
let headHeight = parseFloat(getComputedStyle(this.prizeBox, ':before').getPropertyValue('height')),
footerHeight = parseFloat(getComputedStyle(this.prizeBox, ':after').getPropertyValue('height')),
innerOffsetTop = 0.12458,
footerOffsetTop = 0.595,
h = this.prizeList.scrollHeight,
scrollListHeight = headHeight + h - (innerOffsetTop * headHeight) - (footerOffsetTop * footerHeight) + footerHeight
this.prizeBox.style.height = `${scrollListHeight}px`
this.innerBox.style.height = `${h}px`
this.bg.style.height = `${h - footerHeight + innerOffsetTop * headHeight}px`
}
return {unfoldList: !prev.unfoldList}
})
}
render() {
const {
showSystemNotices
} = this.props
return (
<>
{showSystemNotices && <SystemBulletScreen/>}
<div className={'prizes-box'} ref={el => this.prizeBox = el}>
<a href="javascript:;" className='rule-btn' onClick={this.showRules}>活动规则 > </a>
<div className={`bg`} ref={el => this.bg = el}/>
<div className={`inner-box`} ref={el => this.innerBox = el}>
<ul className='prize-list' ref={el => this.prizeList = el}>
{
this.state.prizes.map((item, index) => {
return (
<li key={index}>
<img src={item.img_name} alt=""/>
{
item.is_captain != 0 && <span className='captain top-tag'>队长专属</span>
}
{
item.mode === 2 && <span className='stage top-tag'>{item.stage_no}次必中</span>
}
{
item.grant_max
?
<div className='bottom-bar'>
<div className="progress-bar"><span className={'progress'}/></div>
<span>限量{item.grant_max}</span>
</div>
: <span className='no-limit'>不限量</span>
}
</li>
)
})
}
</ul>
</div>
<div className="show-more" onClick={this.showMore}>
{
this.state.unfoldList
? <div>
收起
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/fold-icon.png" alt=""/>
</div>
: <div>
查看全部奖品
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/unfold-icon.png" alt=""/>
</div>
}
</div>
</div>
</>
)
}
}
export default Prizes
.trans-height {
transition: height .25s ease-in-out;
}
.prizes-box {
@extend .trans-height;
position: relative;
height: 348px;
background-size: 100% auto;
.show-more {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
width: 125px;
height: 27px;
background: #FF2121;
border: 2px solid rgba(255, 33, 33, 1);
border-radius: 5px 5px 0 0;
font-size: 13px;
color: #fff;
line-height: 27px;
text-align: center;
z-index: 20;
img {
margin-left: 4.5px;
width: 10.05px;
}
}
.rule-btn {
position: absolute;
top: 32.5px;
left: 50%;
transform: translateX(-50%);
color: #FFDD1D;
font-size: 12px;
text-decoration: underline;
}
@mixin common-deco($bg) {
content: '';
display: block;
width: 100%;
background: url($bg) no-repeat;
background-size: contain;
}
&::before {
@include common-deco('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/landing-box-head.png');
height: 148.5px;
}
&::after {
@include common-deco('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/landing-box-footer.png');
height: 85px;
}
.bg {
@extend .trans-height;
width: 100%;
height: 115px;
overflow: hidden;
z-index: 10;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/landing-box-bg.png") repeat-y;
background-size: 100% auto;
}
.inner-box {
@extend .trans-height;
position: absolute;
top: 130px;
left: 0;
width: 100%;
z-index: 20;
height: 187px;
overflow: hidden;
}
.prize-list {
display: flex;
flex-flow: wrap;
padding: 0 57px;
& li:nth-of-type(2n) {
margin-right: 0;
}
li {
position: relative;
width: 125px;
height: 99px;
background: rgba(255, 255, 255, 1);
border: 2px solid rgba(255, 227, 0, 1);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
border-radius: 1px;
margin-right: 10.5px;
margin-bottom: 6.5px;
img {
width: 90px;
object-fit: contain;
}
}
.top-tag {
position: absolute;
top: 0;
right: 0;
border-radius: 0 0 0 4px;
font-size: 12px;
line-height: 16px;
text-align: center;
padding: 0 4px;
color: #fff;
}
.captain {
background: linear-gradient(270deg, rgba(255, 93, 0, 1) 0%, rgba(255, 23, 0, 1) 100%);
}
.stage {
background: linear-gradient(-90deg, rgba(0, 75, 251, 1) 0%, rgba(0, 156, 255, 1) 100%);
}
.no-limit {
position: absolute;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, .8);
font-size: 12px;
color: #fff;
padding: 4px;
border-radius: 6px 0 0 0;
}
.bottom-bar {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
//height: 18px;
padding: 0 5px;
display: flex;
justify-content: space-between;
align-items: center;
background: rgba(0, 0, 0, .8);
font-size: 12px;
color: #fff;
.progress-bar {
position: relative;
flex: 0 1 50px;
height: 2px;
background: #fff;
.progress {
position: absolute;
right: 0;
top: 0;
width: 80%;
height: 100%;
background: linear-gradient(-90deg, rgba(255, 140, 0, 1) 0%, rgba(255, 23, 0, 1) 100%);
border-radius: 1px;
}
}
}
}
}
import React, { Component } from 'react'
import Swiper from 'swiper'
import 'swiper/dist/css/swiper.min.css'
import './system-bullet-screen.scss'
class SystemBulletScreen extends Component {
swiper
count = 0
sysNotice
state = {
showNotices: true
}
componentDidMount() {
this.initializeSwiper()
}
componentWillUnmount() {
this.swiper && this.swiper.destroy(true, true)
}
initializeSwiper = () => {
const _this = this
this.swiper = new Swiper('.sys-bullet-screen-swiper-container', {
allowTouchMove: false,
direction: 'vertical',
loop: true,
on: {
init() {
Array.from(this.slides).forEach(item => {
item.querySelector('span').addEventListener('transitionend', _this.transitionEnd)
})
},
slideChangeTransitionEnd() {
_this.slideHorizontal(this)
},
transitionEnd() {
const el = this.slides[this.previousIndex].querySelector('span')
el.style.transition = 'unset'
el.style.transform = 'translate3d(0,0,0)'
}
}
})
}
slideHorizontal = (swiper) => {
let el = swiper.slides[swiper.activeIndex],
content = el.querySelector('span'),
contentWidth = content.offsetWidth,
wrapperWidth = el.clientWidth
const co = 131.25
if (contentWidth > wrapperWidth) {
content.style.transition = `transform ${contentWidth / co}s linear`
setTimeout(() => {
content.style.transform = `translate3d(${-(contentWidth - wrapperWidth) - 10}px,0,0)`
}, 1000)
} else {
this.swiper.slideNext()
}
}
transitionEnd = () => {
const {
bullets = [
'第一条消息,第一条消息,第一条消息,第一条消息,第一条消息,第一条消息,',
'第二条消息,第二条消息,第二条消息,第二条消息,第二条消息,第二条消息,',
'第三条消息,第三条消息,第三条消息,第三条消息,第三条消息,第三条消息,',
]
} = this.props
const len = bullets.length * 3
if (++this.count === len) {
setTimeout(() => {
this.sysNotice.style.height = `0px`
}, 2000)
} else {
setTimeout(() => {
this.swiper && this.swiper.slideNext()
}, 1000)
}
}
removeSystemNotices = e => {
e.persist()
if(e.target === this.sysNotice){
this.setState({
showNotices: false
})
}
}
render() {
const {
bullets = [
'第一条消息,第一条消息,第一条消息,第一条消息,第一条消息,第一条消息,',
'第二条消息,第二条消息,第二条消息,第二条消息,第二条消息,第二条消息,',
'第三条消息,第三条消息,第三条消息,第三条消息,第三条消息,第三条消息,',
]
} = this.props
return (
this.state.showNotices &&
<div id="system-bullet-screen" onTransitionEnd={this.removeSystemNotices} ref={el => this.sysNotice = el}>
<img className='avatar'
src='https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/system-avatar.png' alt=""/>
<div className='sys-bullet-screen-swiper-container'>
<ul className="swiper-wrapper">
{
bullets && bullets.length && bullets.map((item, index) => {
return (
<li className="swiper-slide" key={index}>
<span>{item}</span>
</li>
)
})
}
</ul>
</div>
</div>
)
}
}
export default SystemBulletScreen
@import "../user-bullet-screen/bullet-screen";
#system-bullet-screen {
overflow: hidden;
margin-top: 11px;
margin-bottom: 16px;
padding-left: 2px;
display: flex;
align-items: center;
transition: height .3s ease-in-out;
.sys-bullet-screen-swiper-container{
height: 100%;
}
ul {
flex: auto;
max-width: 293px;
}
li {
overflow: hidden;
height: 30px;
span {
display: inline-block;
white-space: nowrap;
line-height: 30px;
}
}
@extend .bullet-screen;
}
.bullet-screen{
width: 329px;
height: 30px;
margin: 0 auto 28px;
background: rgba(0, 0, 0, .6);
border-radius: 15px;
line-height: 30px;
text-align: left;
li {
height: 100%;
padding: 2px;
line-height: 26px;
}
.avatar {
width: 26px;
height: 26px;
border-radius: 50%;
margin-right: 7px;
vertical-align: middle;
}
& span:nth-of-type(1) {
margin-right: 5px;
}
span {
font-size: 12px;
color: #fff;
}
}
#user-bullet-screen {
@extend .bullet-screen
}
import React, { Component } from 'react'
import { http } from "@/utils"
import Swiper from 'swiper'
import 'swiper/dist/css/swiper.min.css'
import './bullet-screen.scss'
class UserBulletScreen extends Component {
state = {
bulletScreenData: []
}
componentDidMount() {
this.getBulletScreenData(true)
}
initializeBulletScreen = () => {
const _this = this
const slidesPerRequest = 20
const indexArray = [...Array(slidesPerRequest - 1).keys()]
let removed = false
this.swiper = new Swiper('.swiper-container', {
direction: 'vertical',
allowTouchMove: false,
autoplay: true,
on: {
transitionEnd() {
if (this.slides.length > slidesPerRequest) {
this.removeSlide(0)
this.autoplay.start()
}
if (this.activeIndex === this.slides.length - 1 && !removed) {
this.autoplay.stop()
_this.getBulletScreenData().then(res => {
removed = true
this.removeSlide(indexArray)
this.appendSlide(_this.getSlides(res))
setTimeout(() => {
this.autoplay.start()
removed = false
})
})
}
}
}
})
}
getSlides = list => list.map(item => {
return `
<li class="swiper-slide">
<img class="avatar" src="${item.avatar_file}" alt="">
<span>${item.user_name}</span>
<span>${item.msg}</span>
</li>
`
})
getBulletScreenData = (initializeSwiper = false) => {
return http.get(`${API.home}/sys/barrage_data`)
.then(res => {
const {data, code} = res.data
if (code == 200) {
if (initializeSwiper) {
this.setState({
bulletScreenData: data
}, () => {
this.initializeBulletScreen()
})
} else {
return data
}
}
})
}
render() {
const {bulletScreenData} = this.state
return (
<div id="user-bullet-screen" className='swiper-container'>
<ul className='swiper-wrapper'>
{
bulletScreenData.length && bulletScreenData.map((item, index) => {
return (
<li className='swiper-slide' key={index}>
<img src={item['avatar_file']}
alt="" className="avatar"/>
<span>{item.user_name}</span>
<span>{item.msg}</span>
</li>
)
})
}
</ul>
</div>
)
}
}
export default UserBulletScreen
......@@ -56,7 +56,8 @@
.des {
font-size: 14px;
color: #FFDC1E;
span{
span {
display: inline-block;
width: 15px;
height: 15px;
......@@ -67,114 +68,8 @@
}
}
.trans-height {
transition: height .25s ease-in-out;
}
.prizes-box {
@extend .trans-height;
position: relative;
height: 348px;
background-size: 100% auto;
.show-more {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
width: 125px;
height: 27px;
background: #FF2121;
border: 2px solid rgba(255, 33, 33, 1);
border-radius: 5px 5px 0 0;
font-size: 13px;
color: #fff;
line-height: 27px;
text-align: center;
z-index: 20;
img {
margin-left: 4.5px;
width: 10.05px;
}
}
.rule-btn {
position: absolute;
top: 32.5px;
left: 50%;
transform: translateX(-50%);
color: #FFDD1D;
font-size: 12px;
text-decoration: underline;
}
@mixin common-deco($bg) {
content: '';
display: block;
width: 100%;
background: url($bg) no-repeat;
background-size: contain;
}
&::before {
@include common-deco('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/landing-box-head.png');
height: 148.5px;
}
&::after {
@include common-deco('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/landing-box-footer.png');
height: 85px;
}
.bg {
@extend .trans-height;
width: 100%;
height: 115px;
overflow: hidden;
z-index: 10;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/landing-box-bg.png") repeat-y;
background-size: 100% auto;
}
.inner-box {
@extend .trans-height;
position: absolute;
top: 130px;
left: 0;
width: 100%;
z-index: 20;
height: 187px;
overflow: hidden;
}
.prize-list {
display: flex;
flex-flow: wrap;
padding: 0 57px;
& li:nth-of-type(2n) {
margin-right: 0;
}
li {
width: 125px;
height: 99px;
background: rgba(255, 255, 255, 1);
border: 2px solid rgba(255, 227, 0, 1);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
border-radius: 1px;
margin-right: 10.5px;
margin-bottom: 6.5px;
img {
width: 90px;
object-fit: contain;
}
}
}
}
.group {
ul.member {
......@@ -265,7 +160,7 @@
font-family: "HiraginoSansGB-W6", "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
.certainly-prompt{
.certainly-prompt {
margin-top: -43px;
padding-bottom: 16px;
font-size: 14px;
......@@ -273,6 +168,30 @@
}
}
.activity-end{
display: flex;
flex-flow: column;
align-items: center;
margin-top: 26px;
font-size: 14px;
color: #FFE300;
div:first-child{
margin-bottom: 5px;
}
div:nth-child(2){
margin-bottom: 19px;
}
img{
width: 120px;
height: 120px;
margin-bottom: 12px;
}
div:last-child{
color: #fff;
font-size: 12px;
}
}
}
.popup-container {
......@@ -282,7 +201,7 @@
color: #666;
text-align: center;
span{
span {
color: #FF2121;
}
}
......@@ -384,6 +303,12 @@
margin-right: 15px;
}
.avatar {
width: 44px;
height: 44px;
border-radius: 50%;
}
sup {
@extend .sup;
}
......@@ -522,8 +447,8 @@
}
}
.landing-open-in-browser-tip.wechat, .landing-share-tip.wechat{
&.popup-container{
.landing-open-in-browser-tip.wechat, .landing-share-tip.wechat {
&.popup-container {
&::after {
content: '';
display: block;
......@@ -538,8 +463,8 @@
}
}
.landing-open-in-browser-tip{
&.popup-container{
.landing-open-in-browser-tip {
&.popup-container {
width: 312px;
}
}
......@@ -58,3 +58,7 @@
}
}
}
.year-index + .year19-index{
display: none;
}
\ 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