Commit 4652d3c7 by wangshuo

合并00

parents c98fb3f6 c52d5a84
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
......@@ -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
.captcha-container {
position: relative;
width: 100%;
height: 40px;
// height: 40px;
}
.captcha-animation {
......
import React, { Component } from 'react';
import { http } from '@/utils';
import { Formik, Form, Field } from 'formik';
import { Toast } from "antd-mobile";
import './index.scss';
class AddressPopup extends Component {
constructor(props) {
super(props)
this.state = {
isLoading: false,
addressInfo: {
name: '',
phone: '',
address: '',
},
}
}
componentDidMount() {
this.fetchUserAddress();
}
// 获取收货信息
fetchUserAddress = () => {
const { addressInfo } = this.state;
http.get(`${API.home}/sys/user_address_info`).then(res => {
const {code, data, msg} = res.data;
if (code === 200) {
this.setState({
addressInfo: Object.assign({}, addressInfo, {
name: data.name,
phone: data.phone,
address: data.address,
}),
isLoading: true,
});
}
});
}
handleToSubmit = (params = {}) => {
const { successBindAddress } = this.props;
http.post(`${API.home}/sys/update_address`, {
act_type: 'treasure',
...params
}).then(res => {
const {code, msg} = res.data;
if (code === 200) {
successBindAddress();
} else {
Toast.info(msg, 2, null, false);
}
});
}
render() {
const { isLoading, addressInfo } = this.state;
const {tip, prize, skip = 'default'} = this.props;
return (
<>
{
isLoading &&
<Formik
initialValues={{
...addressInfo
}}
validate={({name, phone, address}) => {
const errors = {};
if (!name) {
errors.name = '请输入收件人';
}
if(!/^1[3-9]\d{9}$/.test(phone)) {
errors.phone = '请填写正确格式的手机号';
}
if (!address) {
errors.address = '请输入收货地址';
}
return errors;
}}
validateOnBlur={false}
validateOnChange={false}
onSubmit={(values) => {
this.handleToSubmit(values);
}}
render={({errors}) => (
<Form className="address-form" data-skip={skip}>
<h2 className="address-form__title">收货信息</h2>
{
prize ? (
<p className='address__prize'>
您抽中了
<span style={{'color': '#FF4000'}}>{prize}</span>
</p>
) : (null)
}
{
tip ? (<div className="address-form__subtitle">{tip}</div>) : (<p className="address-form__desc">请及时填写收货信息,获得实物奖品后将第一时间为您邮寄</p>)
}
<Field
name="name"
render={({ field }) => (
<div className="address-form__item">
<input
{...field}
className="address-form__ipt"
type="text"
placeholder="收件人"
/>
{
errors.name &&
<p className="address-form__tip">{errors.name}</p>
}
</div>
)}
/>
<Field
name="phone"
render={({ field }) => (
<div className="address-form__item">
<input
{...field}
className="address-form__ipt"
type="text"
placeholder="联系方式"
/>
{
errors.phone &&
<p className="address-form__tip">{errors.phone}</p>
}
</div>
)}
/>
<Field
name="address"
render={({ field }) => (
<div className="address-form__item">
<input
{...field}
className="address-form__ipt"
type="text"
placeholder="收货地址"
/>
{
errors.address &&
<p className="address-form__tip">{errors.address}</p>
}
</div>
)}
/>
<button
className="address-form__submit"
data-status="do"
type="submit"
>提交</button>
</Form>
)}
/>
}
</>
);
}
}
export default AddressPopup;
\ No newline at end of file
// 地址弹窗
[data-skip="default"] {
.address-form__item {
width: 250px;
}
.address-form__submit {
width: 120px;
height: 34px;
margin: 8px auto 0;
border-style: none;
border-radius: 17px;
color: rgba(255, 255, 255, 1);
background-color: rgba(82, 92, 101, 0.3);
&[data-status="do"] {
background-color: #0099FF;
}
}
}
[data-skip="year"] {
.address-form__title {
margin: 10px 0 0;
font-size: 18px;
color: #111;
text-align: center;
line-height: 1;
}
.address-form__subtitle {
margin: 0 15px;
}
.address-form__item {
width: 270px;
margin: 0 15px 10px;
}
.address-form__ipt {
border-radius: 3px;
}
.address-form__submit {
width: 270px;
height: 44px;
margin: 15px auto 0;
border: 1px solid #090909;
border-radius: 5px;
color: #090909;
background-color: #FFE319;
}
}
.address-form__desc {
// width: 238px;
margin: 16px auto 15px;
font-size: 12px;
color: #999;
}
.address-form__item {
position: relative;
width: 250px;
margin: 0 auto 16px;
}
.address-form__ipt {
display: block;
width: 100%;
height: 40px;
border: 1px solid rgba(221, 221, 221, 1);
font-size: 14px;
font-weight: 400;
color: rgba(153, 153, 153, 1);
text-indent: 10px;
}
.address-form__tip {
position: absolute;
bottom: -14px;
width: 100%;
font-size: 12px;
color: #ff0000;
line-height: 14px;
}
.address-form__submit {
display: block;
font-size: 15px;
font-weight: 500;
cursor: pointer;
outline: none;
}
\ No newline at end of file
import React, { Component } from 'react';
import { Formik, Form, Field } from 'formik';
import { Toast } from 'antd-mobile';
import { isEmpty } from 'lodash';
import Captcha from '@/common/Captcha';
import { http, getParam } from '@/utils';
import './index.scss';
class BindPhone extends Component {
captchaInstance = null;
constructor(props) {
super(props),
this.state = {
validate: '',
seconds: 60,
isFirst: true,
timer: null,
isTimer: false, // 是否开始倒计时
accountInfo: {},
bindInfo: {},
country: {
num: '86'
}
}
}
componentDidMount() {
this.initCountryInfo();
}
initCountryInfo = () => {
const { country } = this.props;
this.setState({
country
});
}
toFetchCountryNum = () => {
const { history, hideBindPhone } = this.props;
hideBindPhone();
history.push('/country?from=bind');
}
getCaptchaInstance = instance => {
this.captchaInstance = instance;
}
onVerify = (err, data) => {
if (err) {
console.log(err);
} else {
this.setState({
validate: data.validate
});
}
}
// 获取手机号验证码
handleToSend = ({tel, code}) => {
let { validate, seconds, isFirst, isTimer, country: {num = '86'} } = this.state;
if(validate) {
if (!isFirst) {
Toast.info('请重新进行滑块验证', 2, null, false);
this.captchaInstance.refresh();
this.setState({
isFirst: true
});
return
}
if(!isTimer) {
if (!tel) {
Toast.info('手机号码不能为空', 2, null, false);
}else if(!/^\d+$/.test(tel)) {
Toast.info('请输入正确格式的手机号码', 2, null, false);
}else {
// 获取验证码
http.post(
`${API['passport-api']}/m/personal/bindPhoneSendCode`,
{
area_code: `00${num}`,
phone_num: tel
}
).then(res => {
const { errno, msg } = res.data;
if(errno === 200) {
Toast.info('验证码发送成功', 2, null, false);
// 倒计时
this.timer = window.setInterval(() => {
if (seconds <= 0) {
window.clearInterval(this.timer);
this.setState({
isTimer: false,
seconds: 60
});
}else {
this.setState({
isTimer: true,
seconds: --seconds
});
}
}, 1000);
// 滑块
this.setState({
isFirst: false
})
}else {
Toast.info(msg, 2, null, false);
}
})
}
}
}
return false;
}
// 绑定手机
toBindPhone = () => {
const { accountInfo: { tel, code }, country: {num = '86'} } = this.state;
const { handleToConfirmPhone, successBindPhone } = this.props;
const params = {
area_code: `00${num}`,
mobile: tel,
code: code,
act_type: 'treasure', // 宝箱
};
http.post(
`${API.home}/sys/v2/user/bindMobile`,
{
...params,
type: 1, // 1:绑定,2:修改绑定
is_valid: 1, // is_valid 是否验证 1:验证(默认),0不验证
}
).then(res => {
const { code, data, msg } = res.data;
if(code === 200 ) {
if(data.tip_info) {
handleToConfirmPhone(params, data.tip_info);
}else {
successBindPhone();
}
}else {
Toast.info(msg, 2, null, false);
}
});
}
render() {
const { desc, skip = 'year' } = this.props;
const { country, validate, isTimer, seconds } = this.state;
return (
<Formik
initialValues={{
tel: '',
code: ''
}}
validate={({tel, code}) => {
const errors = {};
// if (!validateTel(tel)) {
if(!/^\d+$/.test(tel)) {
errors.tel = '请填写正确格式的手机号';
}
if (!/[0-9]{6}/.test(code)) {
errors.code = '请输入验证码';
}
return errors;
}}
onSubmit={(values, { setStatus, setSubmitting }) => {
this.setState({
accountInfo: {
...values
}
});
this.toBindPhone();
}}
render={({values: {tel, code}, errors}) => (
<Form className="popup-form" data-skip={skip}>
<h2 className="popup-form__title">绑定手机号</h2>
{
desc &&
<div className="poup-form__desc">{desc}</div>
}
<div className="popup-form__item">
<a className="popup-form__button--num" onClick={this.toFetchCountryNum}>
+{country.num}
<i className="iconfont iconiconfront-69"/>
</a>
<Field
name="tel"
render={({field}) => {
return (
<input
{...field}
className="popup-form__ipt"
data-type="tel"
type="text"
placeholder="请填写手机号"
/>
);
}}
/>
</div>
<Captcha
getInstance={this.getCaptchaInstance}
onVerify={this.onVerify}
/>
<div className="popup-form__item">
<Field
name="code"
render={({field}) => {
return (
<input
{...field}
className="popup-form__ipt popup-form__ipt--left"
type="text"
placeholder="输入验证码"
/>
);
}}
/>
<button
className="popup-form__button--code"
data-status={(validate && !isTimer)? 'do': ''}
type="button"
onClick={() => this.handleToSend({tel, code})}
>
{
isTimer? `重新发送${seconds}s` : '发送验证码'
}
</button>
</div>
<button
className="popup-form__button--bundle"
data-status={(tel && code && isEmpty(errors))? 'do': 'done'}
type="submit"
>
完成绑定
</button>
</Form>
)}
/>
)
}
}
export default BindPhone;
\ No newline at end of file
// form
// .popup-form {
// text-align: center;
.popup-packet__button--bundle {
margin-top: 5px;
}
// }
[data-skip="default"] {
.popup-form__item {
height: 36px;
}
.popup-form__button--num {
border: 1px solid #99D6FF;
border-right-style: none;
border-radius: 6px 0 0 6px;
}
.popup-form__button--code {
border-radius: 6px;
}
.popup-form__button--bundle {
width: 161px;
height: 30px;
border-radius: 15px;
font-size: 13px;
}
.popup-form__ipt {
border: 1px solid #99D6FF;
border-radius: 6px;
&[data-type="tel"] {
border-left-style: none;
border-radius: 0 6px 6px 0;
}
}
}
[data-skip="year"] {
.popup-form__title {
margin: 10px 0 0;
font-size: 18px;
color: #111;
text-align: center;
line-height: 1;
}
.popup-form__item {
width: 269px;
height: 40px;
}
.popup-form__button--num {
border: 1px solid #CDCDCD;
border-right-style: none;
border-radius: 3px 0 0 3px;
}
.popup-form__button--code {
border-radius: 3px;
}
.popup-form__button--bundle {
width: 270px;
height: 44px;
margin-bottom: 14px;
border-radius: 5px;
font-size: 16px;
}
.popup-form__ipt {
border: 1px solid #CDCDCD;
border-radius: 3px;
&[data-type="tel"] {
border-left-style: none;
border-radius: 0 3px 3px 0;
}
}
}
.captcha-container {
width: 269px;
height: 40px;
margin: 0 auto 15px;
}
.popup-form {
// width: 290px;
// height: 257px;
// padding: 20px 20px 0;
box-sizing: border-box;
}
.popup-form__item {
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 15px;
.popup-form__ipt {
flex: 1;
}
.popup-form__ipt--left {
width: 130px;
}
.popup-form__button--code {
margin-left: 10px;
}
}
.popup-form__button--num {
display: block;
position: relative;
height: 36px;
padding: 0 8px;
box-sizing: border-box;
font-size: 14px;
color: #333;
line-height: 36px;
&::after {
display: block;
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 1px;
height: 14px;
margin: auto 0;
background-color: #AAAAAA;
}
.iconfont {
font-size: 12px;
color: #333;
}
}
.popup-form__ipt {
height: 36px;
padding: 0 8px;
box-sizing: border-box;
font-size: 12px;
color: #999;
line-height: 36px;
outline: none;
&[data-type="tel"] {
border-left-style: none;
}
}
.popup-form__tip {
margin: 0;
font-size: 12px;
color: #FF3131;
.iconfont {
font-size: 15px;
color: #FF3131;
}
}
.popup-form__button--code {
width: 110px;
height: 36px;
padding: 0;
border: 1px solid #E5E5E5;
box-sizing: border-box;
font-size: 13px;
color: #999;
text-align: center;
line-height: 36px;
background-color: transparent;
&[data-status='do'] {
border-color: #0099FF;
color: #0099FF;
}
}
.popup-form__button--bundle {
display: block;
padding: 0;
margin: 0 auto;
border-style: none;
color: #2B2B2B;
background-color: #F9DB4A;
cursor: pointer;
&[data-status="done"] {
color: #fff;
background-color: #ABABAB;
}
&[data-status='do'] {
color: #fff;
background-color: #0099FF;
}
}
\ No newline at end of file
......@@ -3,11 +3,25 @@ import ReactDOM from 'react-dom'
import './index.scss'
import classnames from 'classnames'
const re = /(https?|ftp):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/
function ClosablePopup({
title, content, className, closable = true, close = function () {
title,
content,
className,
closable = true,
close = function () {
},
clickMaskClose = true,
closeIcon = 'iconiconfront-2',
afterClose = function () {
},
remove = function () {
}
} = {}) {
function unmountComponent() {
ReactDOM.unmountComponentAtNode(div)
if (div && div.parentNode) {
......@@ -20,22 +34,36 @@ function ClosablePopup({
if (_c && _c.then) {
_c.then(() => {
unmountComponent()
afterClose()
})
} else {
unmountComponent()
afterClose()
}
}
function clickMask() {
if (closable) {
return
}
if (!clickMaskClose) {
return
}
_close()
}
const closablePopup = (
<div className={'closable-popup-mask'}>
<div className={'closable-popup-mask'} onClick={clickMask}>
<div className={classnames(['popup-container', className])}>
<div className="title">{title}</div>
<div className="content">
{content}
</div>
{
closable && <i className={'close iconfont iconiconfront-2'} onClick={_close}/>
closable &&
(re.test(closeIcon)
? <img src={closeIcon} alt="" className={'close-icon'} onClick={_close}/>
: <i className={`close iconfont ${closeIcon}`} onClick={_close}/>)
}
</div>
</div>
......@@ -47,7 +75,8 @@ function ClosablePopup({
ReactDOM.render(closablePopup, div)
return {
close: _close
close: _close,
remove: unmountComponent
}
}
......
......@@ -31,5 +31,16 @@
font-size: 36px;
color: #fff;
}
.close-icon {
position: absolute;
bottom: -66px;
left: 50%;
width: 33px;
height: 33px;
transform: translateX(-50%);
font-size: 36px;
color: #fff;
}
}
}
import React, { Component } from 'react';
import { Toast } from 'antd-mobile';
import { http } from '@/utils';
import './index.scss';
class ConfirmPhone extends Component {
continueBindPhone = () => {
const { data, successBindPhone } = this.props;
http.post(
`${API.home}/sys/v2/user/bindMobile`,
{
...data,
type: 1, // 1:绑定,2:修改绑定
is_valid: 0, // is_valid 是否验证 1:验证(默认),0不验证
}
).then(res => {
const { code, msg } = res.data;
if(code === 200 ) {
successBindPhone();
}else {
Toast.info(msg, 2, null, false);
}
});
}
render() {
const {
bindInfo = { },
desc,
skip = 'year',
handleToCancle
} = this.props;
return (
<div className="popup-bind" data-skip={skip}>
<h2 className="popup-bind__title">绑定手机号</h2>
{
desc
? <div className="popup-bind__desc">{desc}</div>
: <p className="popup-bind__desc">该手机号已绑定到以下账号,继续绑定将解除以下绑定状态</p>
}
<ul className="popup-bind__list">
{
bindInfo['email'] &&
<li className="popup-bind__account">
{/* 邮箱 */}
<i className="popup-bind__icon" data-plat="mail"></i>
<p className="popup-bind__account--name">{bindInfo['email']}</p>
</li>
}
{
bindInfo['wechat_nickname'] &&
<li className="popup-bind__account">
{/* wechat */}
<i className="popup-bind__icon" data-plat="wachat"></i>
<p className="popup-bind__account--name">{bindInfo['wechat_nickname']}</p>
</li>
}
{
bindInfo['qq_nickname'] &&
<li className="popup-bind__account">
{/* qq */}
<i className="popup-bind__icon" data-plat="qq"></i>
<p className="popup-bind__account--name">{bindInfo['qq_nickname']}</p>
</li>
}
{
bindInfo['sina_nickname'] &&
<li className="popup-bind__account">
{/* 微博 */}
<i className="popup-bind__icon" data-plat="sina"></i>
<p className="popup-bind__account--name">{bindInfo['sina_nickname']}</p>
</li>
}
</ul>
<div className="popup-bind__footer">
<button
className="popup-bind__button popup-bind__button--cancle"
onClick={handleToCancle}>取消</button>
<button
className="popup-bind__button popup-bind__button--confirm"
onClick={this.continueBindPhone}>继续绑定</button>
</div>
</div>
)
}
}
export default ConfirmPhone;
\ No newline at end of file
[data-skip="default"] {
.popup-bind__desc {
width: 249px;
font-size: 15px;
color: #666;
line-height: 21px;
}
.popup-bind__account {
padding: 4px;
}
.popup-bind__account--name {
padding-left: 7px;
font-size: 12px;
color: #999;
}
.popup-bind__icon {
width: 22px;
height: 22px;
}
.popup-bind__footer {
padding: 0 18px;
}
.popup-bind__button {
width: 105px;
height: 30px;
border-radius: 15px;
font-size: 14px;
}
.popup-bind__button--cancle {
border: 1px solid #0099FF;
color: #0099FF;
}
.popup-bind__button--confirm {
border-style: none;
color: #fff;
background-color: #0099FF;
}
}
[data-skip="year"] {
.popup-bind__title {
margin: 10px 0 0;
font-size: 18px;
color: #111;
line-height: 1;
text-align: center;
}
.popup-bind__desc {
width: 269px;
font-size: 12px;
color: #FF2121;
line-height: 18px;
}
.popup-bind__account {
padding: 14px 4px;
}
.popup-bind__account--name {
padding-left: 12px;
font-size: 15px;
color: #090909;
}
.popup-bind__icon {
width: 33px;
height: 33px;
}
.popup-bind__footer {
padding: 0 15px;
margin-bottom: 14px;
}
.popup-bind__button {
width: 130px;
height: 44px;
border-radius: 5px;
font-size: 16px;
}
.popup-bind__button--cancle {
border: 1px solid #090909;
color: #090909;
}
.popup-bind__button--confirm {
border: 1px solid #090909;
color: #090909;
background-color: #FFE319;
}
}
.popup-bind {
text-align: center;
}
.popup-bind__desc {
margin: 10px 15px 0;
text-align: left;
}
.popup-bind__list {
padding: 0 0 10px;
}
.popup-bind__account {
display: flex;
align-items: center;
margin: 0 52px;
text-align: left;
&:nth-child(n+2) {
border-top: 1px solid #E5E5E5;
}
}
.popup-bind__account--name {
margin: 0;
}
.popup-bind__icon {
display: inline-block;
background-size: auto 100%;
background-repeat: no-repeat;
background-position: center;
&[data-plat="mail"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-mail.png');
}
&[data-plat="sina"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-sina.png');
}
&[data-plat="qq"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-qq.png');
}
&[data-plat="wachat"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-wechat.png');
}
}
.popup-bind__footer {
display: flex;
align-items: center;
justify-content: space-between;
}
.popup-bind__button {
box-sizing: border-box;
cursor: pointer;
outline: none;
}
.popup-bind__button--cancle {
background-color: transparent;
}
\ No newline at end of file
......@@ -740,6 +740,10 @@
// //}
}
.index-box + .nav-bar + .year19-index{
display: none;
}
.borderTop {
width: 100%;
height: 8px;
......
......@@ -6,13 +6,13 @@
.banner__con {
width: 100%;
height: 170px;
background: url('./images/formal-banner.png') center center no-repeat;
background: url('images/formal-banner.png') center center no-repeat;
background-size: 100% 100%;
}
.content__con {
width: 100%;
height: 454px;
background: url('./images/dalibao_bj.png') center center no-repeat;
background: url('images/dalibao_bj.png') center center no-repeat;
background-size: 100% 100%;
position: relative;
......@@ -55,7 +55,7 @@
.img__con {
width: 88px;
height: 16px;
background: url('./images/value.png') center center no-repeat;
background: url('images/value.png') center center no-repeat;
background-size: 100% 100%;
margin-left: 4px;
}
......@@ -186,7 +186,7 @@
font-weight:400;
color:rgba(255,255,255,1);
width: 240px;
background: url('./images/yaoqh_bj.png') center center no-repeat;
background: url('images/yaoqh_bj.png') center center no-repeat;
background-size: 100% 50%;
text-align: center;
text-align-last: center;
......@@ -292,7 +292,7 @@
.share__row {
width: 60px;
height: 44px;
background: url('./images/throw_icon.png') center center no-repeat;
background: url('images/throw_icon.png') center center no-repeat;
background-size: 100% 100%;
position: absolute;
right: 15px;
......
.box-container {
position: relative;
background: #327443;
padding: 14px 0;
.image-box {
height: 100%;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/sd_nr_bj2.png") repeat-y;
background-size: 100% auto;
}
@mixin common-deco($bg) {
content: '';
position: absolute;
left: 0;
width: 100%;
height: 14px;
display: block;
background: url($bg) no-repeat;
background-size: 375px auto;
}
&::before {
@include common-deco("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/sd_nr_bj1.png");
top: 0;
}
&::after {
@include common-deco("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/sd_nr_bj3.png");
bottom: 0;
}
}
import React, { Component } from 'react'
import './box-container.scss'
class Container extends Component {
render() {
return (
<div className={'box-container'}>
<div className="image-box">
{this.props.children}
</div>
</div>
)
}
}
export default Container
import React, { Component } from 'react'
import './index.scss'
export default class CommonContainer extends Component {
constructor(props) {
super(props)
}
render() {
const { id } = this.props;
return (
<div className='common_container' id={id}>
<div className='container_top'></div>
<div className='container_content'>
{
this.props.title &&
<div className='title_container'>
<i></i>
<p>{this.props.title}</p>
<i></i>
</div>
}
{
React.Children.map(this.props.children, function (child) {
return <>{child}</>;
})
}
</div>
<div className='container_bottom'></div>
</div>
)
}
}
.common_container {
margin-bottom: 35px;
.title_container {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
i {
width: 230px;
height: 2px;
margin: auto;
background: linear-gradient(
90deg,
rgba(254, 228, 29, 0) 0%,
rgba(254, 228, 29, 0.98) 48%,
rgba(254, 228, 29, 0) 100%
);
margin: 0 auto;
}
p {
font-size: 18px;
line-height: 18px;
font-weight: 500;
color: rgba(254, 228, 29, 1);
margin: 8px auto;
background: linear-gradient(
0deg,
rgba(254, 228, 29, 1) 23.9013671875%,
rgba(255, 204, 0, 1) 50.146484375%,
rgba(254, 228, 29, 1) 75%
);
background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.container_top {
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_top_bj.png")
center center no-repeat;
background-size: 100% 100%;
width: 100%;
height: 18px;
}
.container_bottom {
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_bottom_bj.png")
center center no-repeat;
background-size: 100% 100%;
width: 100%;
height: 22px;
}
.container_content {
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_middle_bj.png");
background-size: contain;
width: 100%;
min-height: 25px;
padding: 5px 20px;
}
}
import React, { Component } from 'react';
import './index.scss';
export default class index extends Component {
constructor(props) {
super(props);
}
computedStyle = () => {
return {
'top': `${this.props.top}px`,
'width': `${this.props.width}px`
}
}
// 控制点击空白处是否关闭弹窗 需要传递一个boolean属性 mark
closePopup = () => {
if(this.props.mark) {
this.props.closePopup();
}
}
render() {
return (
<div className='popup__container' onClick={this.closePopup}>
<div className='content__container' style={this.computedStyle()} onClick={(e) => {e.stopPropagation()}}>
<img className="close__btn" onClick={this.props.closePopup} src='https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/close-btn.png' alt="" />
{
React.Children.map(this.props.children, function (child) {
return <>{child}</>;
})
}
</div>
</div>
)
}
}
.popup__container {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.6);
z-index: 99;
.content__container {
width: 320px;
min-height: 240px;
border-radius: 5px;
background: rgba(255,255,255,1);
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 160px;
.close__btn {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 33px;
height: 33px;
bottom: -57px
}
}
}
\ No newline at end of file
import React from 'react';
import './index.scss';
export default (props) => {
console.log(props);
const {
data: {
team_num = 1,
lack_member = 4,
member = [],
},
handleToInvite
} = props;
const members = new Array(5).fill({});
return (
<div className="team-success">
<h2 className="team-success__title">创建成功</h2>
<p className="team-success__tip">
{<span>{team_num}</span>}号队伍 还差{<span>{lack_member}</span>}名队员即可获得宝箱哦~
</p>
<i className="team-success__icon"></i>
<ul className='team-success__member members'>
{
members.map((item, index) => {
const _member = member[index]
return (
<li className="member-item" key={index}>
{
_member && _member['is_captain'] && <sup className="member-item__captain">队长</sup>
}
<img
className="member-item__avatar"
src={
_member
? _member['head_img']
: "https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/not-joined-placeholder.png"
}
alt=""/>
</li>
);
})
}
</ul>
<button type={'button'} className="team-success__button" onClick={handleToInvite}>邀请好友加入队伍</button>
</div>
)
}
\ No newline at end of file
.team-success__title {
margin: 10px 0 0;
font-size: 18px;
color: #111;
text-align: center;
line-height: 1;
}
.team-success__tip {
margin: 12px 0 0;
font-size: 15px;
color: #666;
text-align: center;
line-height: 1;
span {
color: #FF2121;
}
}
.team-success__icon {
display: block;
width: 120px;
height: 72px;
margin: 20px auto;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/treasure-box-icon.png');
}
.team-success__member {
display: flex;
padding: 0 12px;
.member-item {
position: relative;
margin: 0 8px;
}
.member-item__captain {
position: absolute;
top: -13px;
right: -10px;
width: 30px;
height: 16px;
border: 1px solid rgba(255, 255, 255, 1);
border-radius: 8px 8px 8px 0;
color: #0E7442;
font-size: 10px;
text-align: center;
line-height: 16px;
background: rgba(255, 227, 0, 1);
}
.member-item__avatar {
width: 44px;
height: 44px;
border-radius: 50%;
}
}
.team-success__button {
display: block;
width: 270px;
height: 44px;
margin: 20px auto;
padding: 0;
border: 1px solid #090909;
border-radius: 5px;
box-sizing: border-box;
font-size: 16px;
color: #090909;
line-height: 44px;
background-color: #FFE319;
}
\ No newline at end of file
import React, { Component } from 'react'
import { http } from "@/utils"
import './prizes.scss'
import { Popup } from "@common/index"
import { Toast } from "antd-mobile"
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
closeIcon = 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/close-btn.png'
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: <div dangerouslySetInnerHTML={{__html: 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,
bottomOffset = 27
this.prizeBox.style.height = `${scrollListHeight + bottomOffset}px`
this.innerBox.style.height = `${h}px`
this.bg.style.height = `${h - footerHeight + innerOffsetTop * headHeight + bottomOffset}px`
}
return {unfoldList: !prev.unfoldList}
})
}
render() {
const {
showSystemNotices
} = this.props
return (
<>
{showSystemNotices && <SystemBulletScreen bullets={this.state.notices}/>}
<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>
)
})
}
<li>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/prize-placeholder.png" alt=""/>
</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 45px;
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;
}
}
}
}
}
.common_container {
.container_content {
.prizes-box {
margin: 0 -20px;
}
}
}
import React, { Component } from 'react';
import { http } from '@/utils';
import './index.scss';
class SplitSuccess extends Component {
computedBg = (val) => {
return val? {
backgroundImage: `url(${val})`
} : {};
}
continueSplitTreasure = () => {
const { ids, successSplitTreasure, handleToBindPhone, handleToBindAddress } = this.props;
const params = ids[0];
http.post(`${API.home}/sys/split_treasure`, params).then(res => {
const { code, data } = res.data;
if(code === 200) {
debugger;
successSplitTreasure(data);
if(data.bind_phone) {
setTimeout(() => {
handleToBindPhone(data.id);
}, 500);
}else if(data.bind_address) {
setTimeout(() => {
handleToBindAddress(data.id);
}, 500);
}
}else if(code === 12000) {
// 请先绑定手机号再拆宝箱
handleToBindPhone();
}else if(code === 12001) {
// 请先填写收货地址再拆宝箱
handleToBindAddress();
}
});
}
render() {
const {
ids,
data: {
member = [],
prize_img,
prize_name,
},
handleToInvite,
children,
} = this.props;
return (
<div data-skip="split">
<h2 className="split-success__title">恭喜你获得</h2>
<div className="split-success__image">
<img src={prize_img} alt=""/>
</div>
<p className="split-success__prize">{prize_name}</p>
{children}
<div className="split-success__member">
{
member.map((item, index) => (
<div className="member-item" key={index}>
<span className="member-item__avatar" style={this.computedBg(item.avatar)}>
{
item.is_captain && <i className="member-item__captain">队长</i>
}
</span>
{
item.prize
? <span className="member-item__prize">{item.prize}</span>
: <span className="member-item__prize">尚未开宝箱</span>
}
</div>
))
}
</div>
{
ids.length > 0
? <button className="split-success__jump" onClick={this.continueSplitTreasure}>继续开宝箱</button>
: <button className="split-success__jump" onClick={handleToInvite}>继续组队开宝箱</button>
}
</div>
);
}
}
export default SplitSuccess;
\ No newline at end of file
[data-skip="split"] {
text-align: center;
.split-success__title {
margin: 10px 0 0;
font-size: 18px;
color: #111;
line-height: 1;
}
.split-success__image {
width: 130px;
height: 103px;
margin: 12px auto 0;
border: 2px solid #CDCDCD;
box-sizing: border-box;
overflow: hidden;
img {
display: block;
width: 100%;
}
}
.split-success__prize {
margin: 8px 0 0;
font-size: 15px;
font-weight: 500;
color: #FF232D;
text-align: center;
line-height: 1;
}
.team-result {
display: inline-block;
margin: 8px 0 0;
font-size: 12px;
color: #666;
text-align: center;
line-height: 1;
span {
text-decoration: underline;
}
}
.split-success__member {
margin: 18px 18px 0;
padding: 4px 12px;
border-radius: 6px;
background-color: #EFEFEF;
}
.member-item {
display: flex;
align-items: center;
margin: 8px 0;
}
.member-item__avatar {
display: inline-block;
position: relative;
width: 25px;
height: 25px;
border-radius: 50%;
background-color: #fff;
background-size: cover;
}
.member-item__captain {
position: absolute;
top: -14px;
right: -18px;
width: 30px;
height: 18px;
border: 1px solid #fff;
border-radius: 9px 9px 9px 0;
font-size: 12px;
font-style: normal;
color: #0B7B45;
text-align: center;
background-color: #FFE319;
}
.member-item__prize {
padding-left: 8px;
font-size: 12px;
color: #090909;
}
.split-success__jump {
width: 270px;
height: 44px;
margin: 18px 25px 8px;
border: 1px solid #090909;
border-radius: 5px;
box-sizing: border-box;
font-size: 16px;
color: #090909;
text-align: center;
line-height: 44px;
background-color: #FFE319;
}
}
\ No newline at end of file
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()
}
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 {
setTimeout(() => {
++this.count;
swiper.slideNext()
}, 3000)
}
}
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 {
@extend .bullet-screen;
overflow: hidden;
margin-top: 11px;
margin-bottom: 16px;
padding-left: 2px;
display: flex;
align-items: center;
transition: height .1s ease-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;
overflow: visible;
line-height: 30px;
}
}
}
.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;
display: flex;
align-items: center;
}
.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;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
#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 {
swiper
state = {
bulletScreenData: []
}
componentDidMount() {
this.getBulletScreenData(true)
}
componentWillUnmount() {
this.swiper && this.swiper.destroy()
}
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} ${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} {item.msg}</span>
</li>
)
})
}
</ul>
</div>
)
}
}
export default UserBulletScreen
import React, { Component } from 'react'
import BoxContainer from '../box-container/container'
import { Toast, WhiteSpace } from "antd-mobile"
import { Popup } from "@common/index"
import { connect } from "react-redux"
import Prizes from "@components/activity/newyear-2019/common/prizes"
import BulletScreen from "@components/activity/newyear-2019/common/user-bullet-screen"
import './landing.scss'
import { browser, getParam, http, wxShare, SendMessageToApp } from "@/utils"
import { Link } from "react-router-dom"
import QRCode from "qrcode"
import YearCourse from '../preheat/YearCourse'
class Landing extends Component {
closeIcon = 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/close-btn.png'
createTeamSuccessPopup = null
joinSuccessPopup = null
swiper = null
state = {
teamData: {
member: []
},
origin: sessionStorage.getItem('isCaptain') ? 1 : getParam('origin'),
treasure_code: getParam('treasure_code'),
activityEnd: false,
notices: [],
rule: '',
isCaptain: getParam('origin') == 1
}
componentDidMount() {
this.fetchPageData()
window.showFollowAlert = this.remind.bind(this, 'create')
}
componentDidUpdate(prevProps) {
if (prevProps.user.hasError !== this.props.user.hasError && !this.props.user.hasError) {
this.fetchPageData()
}
}
fetchPageData = ({origin = this.state.origin, treasure_code = this.state.treasure_code} = {}) => {
http.post(`${API.home}/sys/treasure/team`, {
treasure_code,
origin
})
.then(res => {
const {data, code, msg} = res.data
if (code == 200) {
this.setState({
teamData: data,
isCaptain: sessionStorage.getItem('isCaptain') ? sessionStorage.getItem('isCaptain') : getParam('origin') == 1,
activityEnd: data.status == 5
})
let searchParams = new URLSearchParams(window.location.search)
if (searchParams.get('origin') === '1' && !browser.isWeixin) {
searchParams.set('origin', '2')
sessionStorage.setItem('isCaptain', '1')
window.history.replaceState(null, '', `landing?${searchParams.toString()}`)
}
this.showSharePromptWithParam()
} else {
Toast.info(msg, 2, null, false)
}
})
}
showSharePromptWithParam = () => {
if (sessionStorage.getItem('showShareTip')) {
this.showShareTip()
}
}
joinTeam = () => {
if (this.requiredLogin()) {
return
}
const {treasure_code} = this.state
http.post(`${API.home}/sys/treasure/joinTeam`, {
treasure_code
})
.then(res => {
const {data, code, msg} = res.data
if (code === 200) {
/*
* status
* 1-成功加入
* 2-成功加入组队成功
* 3-已加入当前队伍
* 4-已加入其他队伍
* */
switch (data.status) {
case 1:
case 2:
this.joinSuccess(data)
break
default:
Toast.info(msg, 2, null, false)
}
} else {
Toast.info(msg, 2, null, false)
}
})
}
joinSuccess = ({id, status, my_team: {team_num, lack_member, is_team, treasure_code}}) => {
const {history} = this.props
this.joinSuccessPopup = Popup({
title: <div className={'join-success'}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/check-icon.png" alt=""/>
<div>成功加入队伍</div>
</div>,
className: 'landing-join-success-wrapper',
content: <div>
<div className={'tip'}>
{
status === 2
? '组队成功,恭喜你获得一个宝箱!'
: is_team
? <>您的{<span>{team_num}</span>}号队伍还差{<span>{lack_member}</span>}人即可获得宝箱</>
: '自己当队长,宝箱内有专属奖品哦~'
}
</div>
{
status === 2
? <img style={{width: '150px', marginTop: '23px'}}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/treasure-box.png"
alt=""
onClick={() => {
this.joinSuccessPopup && this.joinSuccessPopup.remove()
history.push(`/year/yearTreasure?id=${id}`)
}}
/>
: is_team
? <button type='button'
onClick={this.inviteMembers.bind(this, treasure_code)}>继续组队</button>
: <button type="button" onClick={this.createMyTeam}>创建我的队伍</button>
}
</div>,
closeIcon: this.closeIcon,
close: () => {
this.fetchPageData()
this.getFollowStatus()
.then(isFollow => {
!isFollow && this.remind('join', this.state.treasure_code, 2)
})
}
})
}
inviteMembers = treasure_code => {
const {history, match, user, location} = this.props
if (browser.isWeixin) {
wxShare({
title: `@${user.data.username} 邀您一起组队拿豪礼!`,
desc: `加入我的队伍,机械键盘,纸质书籍等超多奖品等你拿!`,
link: `${window.location.origin}/${location.pathname}?treasure_code=${treasure_code}&origin=2`,
//todo 分享图片更换
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newIndex/community/tou5_bj.png'
})
}
sessionStorage.setItem('showShareTip', '1')
history.replace(`${match.url}?treasure_code=${treasure_code}&origin=${1}`)
this.createTeamSuccessPopup && this.createTeamSuccessPopup.remove() && (this.createTeamSuccessPopup = null)
this.joinSuccessPopup && this.joinSuccessPopup.remove() && (this.joinSuccessPopup = null)
this.fetchPageData({treasure_code, origin: 1})
this.setState({
isCaptain: true
})
}
getFollowStatus = () => http.get(`${API.home}/sys/user/isFollowWeChat`)
.then(res => {
const {code, data} = res.data
return code === 200 && data['is_follow']
})
createTeamSuccess = ({member, team_num, lack_member, treasure_code}) => {
this.joinSuccessPopup && this.joinSuccessPopup.remove() && (this.joinSuccessPopup = null)
this.getFollowStatus()
.then(isFollow => {
this.createTeamSuccessPopup = Popup({
title: '创建成功',
className: 'landing-create-success',
content: <div>
<div className="tip">{<span>{team_num}</span>}号队伍 还差{<span>{lack_member}</span>}名队员即可获得宝箱哦~</div>
<img className={'treasure-box'}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/treasure-box-icon.png" alt=""/>
<ul className='members'>
{
new Array(5).fill('a').map((item, index) => {
const _member = member[index]
return <li key={index}>
{_member && _member['is_captain'] && <sup>队长</sup>}
<img
className={'avatar'}
src={
_member
? _member['head_img']
: "https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/not-joined-placeholder.png"
}
alt=""/>
</li>
})
}
</ul>
<button type={'button'} onClick={this.inviteMembers.bind(this, treasure_code)}>邀请好友加入队伍</button>
</div>,
closeIcon: this.closeIcon,
afterClose: () => {
if (!isFollow) {
this.remind('create', treasure_code)
}
}
})
})
}
remind = (type = 'create', treasure_code, origin = 1) => {
const {user} = this.props
http.get(`${API["base-api"]}/wx/user_temporary_qrcode/${user.data.uid}`)
.then(res => {
const {data} = res.data
return data.url
})
QRCode.toDataURL('http://m.julyedu.com')
.then(url => {
Popup({
title: '提醒服务',
className: 'landing-remind',
closeIcon: this.closeIcon,
content: <div>
<div className="des">{type === 'create' ? '有好友加入队伍后第一时间通知我~' : '获得宝箱时第一时间通知我~'}</div>
<img src={url} alt=""/>
<div className="des">长按识别/扫码 关注【七月在线】服务号即可预约</div>
</div>,
close: () => {
// history.replace(`${match.path}?treasure_code=${treasure_code}&origin=1`)
this.fetchPageData({
treasure_code,
origin
})
}
})
})
}
showShareTip = () => {
const {user} = this.props
if (browser.isAndroidApp) {
} else if (browser.isIOSApp) {
SendMessageToApp('toShare', {
title: `@${user.data.username} 邀您一起组队拿豪礼!`,
desc: `加入我的队伍,机械键盘,纸质书籍等超多奖品等你拿!`,
link: `${window.location.origin}/${location.pathname}?treasure_code=${getParam('treasure_code')}&origin=2`,
//todo 分享图片更换
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newIndex/community/tou5_bj.png'
})
} else {
const {history, match} = this.props
if (browser.isWeixin && getParam('origin') == 1) {
history.replace(`${match.url}?treasure_code=${getParam('treasure_code')}&origin=2`)
}
Popup({
title: <div>还差<span>{this.state.teamData.lack_member}</span>名队友即可获得宝箱 快分享给好友吧~</div>,
className: `landing-share-tip ${browser.isWeixin ? 'wechat' : ''}`,
closable: false,
close: () => {
sessionStorage.removeItem('showShareTip')
if (!user.hasError) {
this.getFollowStatus()
.then(isFollow => {
!isFollow && this.remind('create', getParam('treasure_code'), 1)
})
}
}
})
}
}
showOpenInBrowserTip = () => {
Popup({
title: <div>点击右上角,选择“在浏览器打开”</div>,
className: 'landing-open-in-browser-tip',
closable: false,
})
}
createMyTeam = () => {
if (this.requiredLogin()) {
return
}
http.get(`${API.home}/sys/treasure/createMyTeam`)
.then(res => {
const {data, code, msg} = res.data
if (code == 200) {
this.createTeamSuccess(data)
} else {
Toast.info(msg, 2, null, false)
}
})
}
requiredLogin = () => {
const {history, user} = this.props
if (user.hasError) {
history.push('/passport')
return true
}
}
render() {
const {
teamData: {
head_img,
member,
status,
lack_member,
team_num,
prize_info,
my_team
},
activityEnd,
isCaptain
} = this.state
/*
* status
* 1-自己的队伍
* 2-未加入队伍
* 3-已加入当前队伍
* 4-已加入别的队伍
* */
return (
<div id={'landing'}>
<div id="to-square">
<Link to='/year/yearindex'>前往活动会场,享更多福利! >></Link>
</div>
<BoxContainer>
<i className="snow-deco"/>
<img className='main-avatar'
src={head_img} alt=""/>
{
status === 1
? <div className="des">邀请好友加入队伍,开宝箱领取丰厚奖品~</div>
: <div className="des">加入我的<span>{team_num}</span>号队伍,一起开宝箱领取丰厚奖品~</div>
}
<Prizes showSystemNotices={false}/>
<BulletScreen/>
<div className="group">
<ul className={'member'}>
{
member && member.length &&
new Array(5).fill('a').map((item, index) => {
const _member = member[index]
return (
_member
? <li key={index}>
<div className='avatar-wrapper'>
{
_member.is_captain ? <sup>队长</sup> : null
}
<img
src={_member.head_img}
alt=""
className="avatar"/>
</div>
</li>
:
<li key={index}>
<div className="avatar-wrapper">
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/default-member-avatar.png"
alt=""
className="avatar"/>
</div>
</li>
)
})
}
</ul>
<ul className={'bars'}>
{
member && member.length &&
new Array(5).fill('a').map((item, index) => {
return (
<li key={index} className={`${index < member.length ? 'active' : ''}`}/>
)
})
}
</ul>
{
status === 1 && !activityEnd &&
<>
<div className="group-des">
还差 {lack_member} 名队员即可获得当前宝箱哦~
</div>
<button type='button' className={'invite-btn'} onClick={this.showShareTip}>
邀请好友加入队伍
</button>
</>
}
{
status === 3 && !activityEnd &&
<>
<div className="group-des">
<p>已加入当前队伍</p>
{
my_team['is_team']
? <p>您的{my_team['team_num']}号队伍还差{my_team['lack_member']}人即可获得宝箱~</p>
: <p>自己当队长,宝箱内有专属奖品哦~</p>
}
</div>
{
my_team['is_team'] ?
<button type='button' className={'invite-btn'}
onClick={this.inviteMembers.bind(this, my_team['treasure_code'])}>
继续组队
</button>
: <button type='button' className={'invite-btn'} onClick={this.createMyTeam}>
创建我的队伍
</button>
}
</>
}
{
status === 4 && !activityEnd &&
<>
<div className="group-des">
<p>已加入其他队伍</p>
{
my_team['is_team']
? <p>您的{my_team['team_num']}号队伍还差{my_team['lack_member']}人即可获得宝箱~</p>
: <p>自己当队长,宝箱内有专属奖品哦~</p>
}
</div>
{
my_team['is_team'] ?
<button type='button' className={'invite-btn'}
onClick={this.inviteMembers.bind(this, my_team['treasure_code'])}>
继续组队
</button>
: <button type='button' className={'invite-btn'} onClick={this.createMyTeam}>
创建我的队伍
</button>
}
</>
}
{
status === 2 && !activityEnd && < button type='button' className={'invite-btn'} onClick={this.joinTeam}>
同意加入队伍
</button>
}
{
prize_info && prize_info.length !== 0 && !activityEnd && !isCaptain && <div className="certainly-prompt">
{prize_info[0].stage_no}次必中 {prize_info[0].name}
</div>
}
{
activityEnd &&
<div className='activity-end'>
<div>活动已结束</div>
<div>关注【七月在线】服务号了解更多活动信息</div>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/tinypng-common/right_weixin.png" alt=""/>
<div>长按识别 / 微信扫码</div>
</div>
}
</div>
</BoxContainer>
{
!isCaptain &&
<>
<WhiteSpace size={'xl'}/>
<YearCourse getSum={() => {
}}/>
</>
}
</div>
)
}
}
export default connect(
state => ({user: state.user}),
null
)(Landing)
.sup {
position: absolute;
right: -10px;
top: -13px;
width: 30px;
height: 16px;
background: rgba(255, 227, 0, 1);
border: 1px solid rgba(255, 255, 255, 1);
border-radius: 8px 8px 8px 0;
color: #0E7442;
font-size: 10px;
text-align: center;
line-height: 16px;
}
#landing {
background: #BC2A18;
text-align: center;
#to-square {
position: fixed;
width: 100%;
height: 30px;
background: #FF2121;
color: #fff;
font-size: 14px;
line-height: 30px;
text-align: center;
z-index: 21;
}
.box-container {
width: 100%;
}
.snow-deco {
position: absolute;
top: 30px;
left: 0;
display: block;
width: 100%;
height: 68px;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/snow-deco.png") no-repeat;
background-size: contain;
}
.main-avatar {
width: 49px;
height: 49px;
border-radius: 50%;
margin-bottom: 5px;
margin-top: 37.5px;
object-fit: cover;
}
.des {
font-size: 14px;
color: #FFDC1E;
span {
display: inline-block;
width: 15px;
height: 15px;
line-height: 16px;
color: #327443;
border-radius: 50%;
background: #FFDC1E;
}
}
.group {
ul.member {
display: flex;
padding: 0 49px;
}
& li:nth-last-child(1) {
margin-right: 0;
}
li {
margin-right: 24.5px;
}
.avatar-wrapper {
position: relative;
&::after {
content: '';
display: block;
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 22px;
height: 3px;
background: #243529;
opacity: 0.8;
border-radius: 50%;
}
sup {
@extend .sup;
}
img {
width: 36px;
height: 36px;
border-radius: 50%;
}
}
.bars {
display: flex;
padding-left: 37.5px;
margin-top: 15px;
& li:nth-child(1) {
border-radius: 2px 0 0 2px;
}
& li:nth-last-child(1) {
border-radius: 0 2px 2px 0;
margin-right: 0;
}
li {
width: 59px;
height: 5px;
margin-right: 1.5px;
background: #035B34;
&.active {
background: #FFDD1D;
}
}
}
&-des {
margin-top: 27px;
font-size: 14px;
color: #FFE300;
}
.invite-btn {
width: 320px;
height: 44px;
line-height: 44px;
margin: 14.5px auto 57px;
color: #0B7B45;
font-size: 15px;
background: #FFE300;
border: 0;
outline: 0;
-webkit-appearance: none;
border-radius: 3px;
font-family: "HiraginoSansGB-W6", "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
.certainly-prompt {
margin-top: -43px;
padding-bottom: 16px;
font-size: 14px;
color: #FFE300;
}
}
.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;
}
}
.am-whitespace.am-whitespace-xl {
height: 35px;
}
}
.popup-container {
.tip {
font-size: 15px;
line-height: 37px;
color: #666;
text-align: center;
span {
color: #FF2121;
}
}
}
.popup-button {
width: 270px;
height: 44px;
padding: 0;
margin-top: 20px;
background: #FFE319;
border: 1px solid #090909;
border-radius: 5px;
line-height: 44px;
font-size: 16px;
color: #090909;
}
.landing-treasure-rules {
width: 320px;
&.popup-container {
.title {
font-size: 18px;
color: #111111;
}
}
.content {
padding: 0 19px 15px;
margin-top: 22px;
color: #666666;
font-size: 14px;
li {
margin-bottom: 5px;
}
}
}
.landing-join-success-wrapper {
&.popup-container {
width: 320px;
text-align: center;
.title {
img {
width: 54px;
height: 54px;
margin-bottom: 10px;
}
font-size: 18px;
color: #111111;
}
}
/*.tip {
font-size: 15px;
line-height: 37px;
color: #666;
text-align: center;
}*/
button {
@extend .popup-button;
}
}
.landing-create-success {
text-align: center;
&.popup-container {
width: 320px;
padding: 20px;
.title {
font-size: 18px;
color: #111111;
}
}
img.treasure-box {
margin: 20px 0;
width: 120px;
height: 72px;
}
.members {
display: flex;
& li:nth-last-child(1) {
margin-right: 0;
}
li {
position: relative;
margin-right: 15px;
}
.avatar {
width: 44px;
height: 44px;
border-radius: 50%;
}
sup {
@extend .sup;
}
}
button {
@extend .popup-button;
}
}
.landing-remind {
&.popup-container {
width: 320px;
text-align: center;
padding: 20px 30px;
.title {
font-size: 18px;
color: #111;
margin-bottom: 8px;
}
}
img {
margin: 18px 0 16px;
width: 137px;
height: 137px;
}
.des {
font-size: 14px;
color: #666;
}
button {
}
}
.landing-open-in-browser-tip, .landing-share-tip {
font-size: 17px;
color: #111;
&.popup-container {
position: absolute;
width: 270px;
text-align: center;
top: 114px;
padding: 20px 33px;
}
span {
color: #FF2121;
}
}
.landing-open-in-browser-tip.wechat, .landing-share-tip.wechat {
&.popup-container {
&::after {
content: '';
display: block;
position: absolute;
top: -50px;
right: -18px;
width: 50px;
height: 38px;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/share-indicator.png") no-repeat;
background-size: contain;
}
}
}
.landing-open-in-browser-tip {
&.popup-container {
width: 312px;
}
}
.year19-index{
display: none;
}
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { HeaderBar } from '@common';
import AddressPopup from '@common/addressPopup/index';
import BindPhone from '@common/bindPhone/index';
import ConfirmPhone from '@common/confirmPhone/index';
import CreateSuccess from './../common/createSuccess/index';
import TreasureTeam from './team';
import PrizeStatus from './prize';
import SplitSuccess from './../common/splitSuccess/index';
import { http, getParam } from '@/utils';
import Mask from './mask';
import './index.scss';
import { split } from 'react-ace';
@connect(({country, user}) => ({
country,
userInfo: user.data
}))
class MyTreasure extends Component {
popupInstance = null;
constructor(props) {
super(props);
this.state = {
isEnd: false,
isEmpty: false,
seconds: 3,
teams: [],
ids: [], // 未拆宝箱统计
bindInfo: {}, // 绑定手机号冲突信息
isPhone: false,
isAddress: false,
isConfirm: false,
confirmInfo: {},
isSplit: false,
isCreate: false,
createInfo: {},
prizeName: '', // 当前商品的名字
};
}
componentDidMount() {
const { isEnd } = this.state;
if (isEnd) {
this.startCountDown();
}
this.fetchMyTreasure();
this.fetchActivityStatus();
}
// 页面加载时,初始化当前需要绑定手机号的奖品名字
initPrizeName = (params) => {
const key = this.fetchCurrentTeamId(params);
const data = params.filter(item => item.id == key);
if(data.length > 0) {
this.setState({
prizeName: data[0]['prize_name']
});
}
}
// 页面加载时,是否需要拆宝箱
judgeIsHaveId = (data) => {
const id = getParam('id');
if(id) {
const newData = data.filter(item => item.id == id);
if(newData.length > 0) {
const params = {
team_num: newData[0]['team_num'],
owner_uid: newData[0]['captain_uid']
};
this.toSplitTreasure(params);
}
}
}
// 获取当前需要绑定手机的队伍id,当拆到需要绑定手机号/地址的宝箱时,如果不进行绑定则无法拆下一个
fetchCurrentTeamId = (data = []) => {
const arr = data.filter(item => item.is_open && (item.bind_phone || item.bind_address));
if(arr.length > 0) {
return arr[0]['id'];
}else {
return '';
}
}
// 页面加载时,是否是从选择区号页面过来的
// TODO,当同时展示拆宝箱成功弹窗和绑定手机号弹窗时,选择区号返回时未展示拆宝箱成功弹窗(和产品确认,后续优化)
isShowBindPhone = (data) => {
const { country } = this.props;
if(country.from) {
const id = this.fetchCurrentTeamId(data);
this.handleToBindPhone(id);
}
}
// 绑定手机号--展示
handleToBindPhone = (id) => {
this.setState({
isPhone: true,
});
}
// 绑定手机号--确认
handleToConfirmPhone = (params, bindInfo) => {
this.handleToHideWindow('isPhone');
this.setState({
confirmInfo: {
params,
bindInfo,
},
isConfirm: true,
});
}
// 绑定手机号--成功
successBindPhone = () => {
this.setState({
isPhone: false,
isConfirm: false,
});
const{ teams, splitInfo } = this.state;
const teamId = this.fetchCurrentTeamId(teams);
const data = teams.map(item => {
if(item.id == teamId) {
if(item.bind_address) {
this.handleToBindAddress();
}
return Object.assign({}, item, {
bind_phone: false,
});
}
return item;
})
this.setState({
teams: data,
splitInfo: Object.assign({}, splitInfo, {
bind_phone: false
})
});
}
// 拆宝箱--拆
toSplitTreasure = (params) => {
http.post(`${API.home}/sys/split_treasure`, params).then(res => {
const { code, data } = res.data;
if(code === 200) {
// 拆宝箱弹窗--成功
this.showSuccessSplit(data);
// 更新队伍状态
this.successSplitTreasure(data);
if(data.bind_phone) {
setTimeout(() => {
this.handleToBindPhone(data.id);
}, 500);
}else if(data.bind_address) {
setTimeout(() => {
this.handleToBindAddress(data.id);
}, 500);
}
}else if(code === 12000) {
// 绑定手机号
this.handleToBindPhone();
}else if(code === 12001) {
// 绑定地址
this.handleToBindAddress();
}
});
}
// 拆宝箱--成功,更新数据
successSplitTreasure = (params) => {
const { userInfo } = this.props;
const { teams } = this.state;
const data = teams.map(item => {
if(item.id == params.id) {
return Object.assign({}, item, {
bind_phone: params.bind_phone,
bind_address: params.bind_address,
is_open: true,
prize_type: params.prize_type,
prize_data: params.prize_data,
member: item.member.map(val => {
if(val.uid == userInfo.uid) {
return Object.assign({}, val, {
is_open: true,
prize_name: params.prize_name
});
}
return val;
})
});
}else {
return item;
}
});
this.initNoSplitInfo(data);
this.setState({
teams: data,
splitInfo: params,
prizeName: params.prize_name
});
}
// 拆宝箱--成功,展示弹窗
showSuccessSplit = (data) => {
this.setState({
isSplit: true,
splitInfo: data
});
}
// 绑定地址--展示
handleToBindAddress = (id) => {
this.setState({
isAddress: true
});
}
// 绑定地址--成功
successBindAddress = () => {
this.setState({
isAddress: false,
});
const{ teams, splitInfo } = this.state;
const teamId = this.fetchCurrentTeamId(teams);
const data = teams.map(item => {
if(item.id == teamId) {
return Object.assign({}, item, {
bind_address: false,
});
}
return item;
})
this.setState({
teams: data,
splitInfo: Object.assign({}, splitInfo, {
bind_address: false
})
});
}
// 获取我的宝箱信息
fetchMyTreasure = () => {
http.get(`${API.home}/sys/treasure/my`).then(res => {
const { code, data } = res.data;
if (code === 200) {
this.setState({
rule: data.rule
});
if (Array.isArray(data.team) && data.team.length > 0) {
this.initNoSplitInfo(data.team);
this.judgeIsHaveId(data.team);
this.isShowBindPhone(data.team);
this.initPrizeName(data.team);
this.setState({
isEmpty: false,
teams: data.team,
});
} else {
this.setState({
isEmpty: true,
});
}
}
});
}
// 统计未拆的宝箱信息
initNoSplitInfo = (data = []) => {
if(data.length > 0) {
this.setState({
ids: data.filter(item => !item.is_open && item.status === 2).map(val => {
return {
team_num: val.team_num,
owner_uid: val.captain_uid
}
})
});
}
}
// 获取宝箱活动状态
fetchActivityStatus = () => {
http.get(`${API.home}/activity/stage`).then(res => {
const { code, data } = res.data;
if (code === 200) {
// treasure_stage,宝箱阶段,0-不在活动时间,1-活动时间内
this.setState({
isEnd: data.treasure_stage === 0
});
}
});
}
// 活动结束--倒计时
startCountDown = () => {
const { history } = this.props;
let { seconds } = this.state;
if (this.timer) {
clearInterval(this.timer);
}
this.setState({
seconds: seconds--
});
this.timer = setInterval(() => {
this.setState({
seconds: seconds--
});
if (seconds === 0) {
this.setState({
seconds: 0
});
clearInterval(this.timer);
history.push('/year/yearIndex');
}
}, 1000);
}
// 邀请好友
handleToInvite = (treasure_code) => {
const { history } = this.props;
history.push(`/activity/newyear-2019/landing?treasure_code=${treasure_code}&origin=1`);
}
// 组队开宝箱
toOrganizeTeam = () => {
const { history, userInfo: { uid = '' } } = this.props;
if(uid === '') {
history.push('/passport')
}else {
http.get(`${API.home}/sys/treasure/createMyTeam`).then(res => {
const { code, data } = res.data;
if(code === 200) {
const teams = [];
teams[0] = data;
this.setState({
isEmpty: false,
teams,
isCreate: true,
createInfo: data
});
}
});
}
}
// 奖品,代金券碎片--合成
toComposeCoupon = () => {
const { history } = this.props;
history.push('/coupons/my-patch');
}
// 奖品,指定课程代金券--使用
toUseCoupon = (id) => {
const { history } = this.props;
history.push(`/detail?id=${id}`);
}
// 第三:奖品,通用课程代金券--使用
toCourseList = () => {
const { history } = this.props;
history.push('/classify');
}
// 第三:奖品,现金红包--提现
toFecthMoney = () => {
const { history } = this.props;
history.push('/scholarship');
}
// 弹窗--隐藏
handleToHideWindow = (key) => {
const param = {};
param[key] = false;
this.setState(param);
}
render() {
const { history, userInfo, country } = this.props;
const {
isEnd,
isEmpty,
seconds,
teams,
ids,
isPhone,
isAddress,
isConfirm,
isSplit,
splitInfo = {},
confirmInfo: {
params = {},
bindInfo = {}
},
isCreate,
createInfo,
prizeName,
rule,
} = this.state;
return (
<div data-skip="treasure">
<HeaderBar title="我的宝箱" arrow={true} />
{
isEnd &&
<p className="activity-end__desc">
活动已结束<br />
{seconds}s后将自动返回首页
</p>
}
{
(!isEnd && isEmpty) &&
<>
<i className="team-empty__icon"></i>
<p className="team-empty__desc">您当前还没有宝箱哦~</p>
<p className="team-empty__desc">快去组队邀请好友一起开宝箱吧!</p>
<button className="team-empty__button" onClick={this.toOrganizeTeam}>组队开宝箱</button>
</>
}
{
(!isEnd && !isEmpty && userInfo.uid) &&
<div className="treasure-content">
{
teams.map((item, index) => (
<TreasureTeam
data={item}
key={index}
userInfo={userInfo}
history={history}
splitInstance={this.splitInstance}
toSplitTreasure={() => this.toSplitTreasure({
team_num: item.team_num,
owner_uid: item.captain_uid
})}
>
<PrizeStatus
data={{
bind_phone: item.bind_phone,
bind_address: item.bind_address,
prize_type: item.prize_type,
}}
handleToBindPhone={this.handleToBindPhone}
handleToBindAddress={this.handleToBindAddress}
toComposeCoupon={this.toComposeCoupon}
toUseCoupon={() => this.toUseCoupon(item.prize_data)}
toCourseList={this.toCourseList}
toFecthMoney={this.toFecthMoney}
/>
</TreasureTeam>
))
}
{/* 拆宝箱--弹窗,成功 */}
<Mask visible={isSplit} handleToHide={() => this.handleToHideWindow('isSplit')}>
<SplitSuccess
ids={ids}
data={splitInfo}
handleToInvite={() => this.handleToInvite(splitInfo.treasure_code)}
handleToBindPhone={this.handleToBindPhone}
handleToBindAddress={this.handleToBindAddress}
successSplitTreasure={this.successSplitTreasure}
>
<PrizeStatus
data={splitInfo}
handleToBindPhone={this.handleToBindPhone}
handleToBindAddress={this.handleToBindAddress}
toComposeCoupon={this.toComposeCoupon}
toUseCoupon={() => this.toUseCoupon(splitInfo.prize_data)}
toCourseList={this.toCourseList}
toFecthMoney={this.toFecthMoney}
/>
</SplitSuccess>
</Mask>
{/*绑定手机号--弹窗 */}
<Mask visible={isPhone} handleToHide={() => this.handleToHideWindow('isPhone')}>
<BindPhone
history={history}
country={country}
hideBindPhone={() => this.handleToHideWindow('isPhone')}
handleToConfirmPhone={this.handleToConfirmPhone}
successBindPhone={this.successBindPhone}
desc={
<>
<p className="phone-treasure__desc">恭喜您获得 奖品名称({prizeName}</p>
<p className="phone-treasure__notice">为了您的账户安全,请于20191231日前绑定手机号,过期将失效</p>
</>
}
/>
</Mask>
{/* 绑定手机号--弹窗,确认 */}
<Mask visible={isConfirm} handleToHide={() => this.handleToHideWindow('isConfirm')}>
<ConfirmPhone
data={params}
bindInfo={bindInfo}
handleToCancle={() => this.handleToHideWindow('isConfirm')}
successBindPhone={this.successBindPhone}
/>
</Mask>
{/* 绑定地址--弹窗 */}
<Mask visible={isAddress} handleToHide={() => this.handleToHideWindow('isAddress')}>
<AddressPopup
skip="year"
tip={
<>
<p className="address-treasure__desc">恭喜您获得 {prizeName}</p>
<p className="address-treasure__notice">请及时填写/确认收货信息,活动结束后统一邮寄</p>
</>
}
successBindAddress={this.successBindAddress}
/>
</Mask>
{/* 组队成功 */}
<Mask visible={isCreate} handleToHide={() => this.handleToHideWindow('isCreate')}>
<CreateSuccess
data={createInfo}
handleToInvite={() => {
this.handleToInvite(createInfo.treasure_code);
this.handleToHideWindow('isCreate');
}}
/>
</Mask>
</div>
}
<div className="activity-rule__header">
<i className="activity-rule__decorate"></i>
<h2 className="activity-rule__title">活动规则</h2>
<i className="activity-rule__decorate"></i>
</div>
<div className="activity-rule__body" dangerouslySetInnerHTML={{__html: rule}}></div>
</div>
)
}
}
export default MyTreasure;
\ No newline at end of file
[data-skip="treasure"] {
min-height: 100vh;
background-color: #0E7442;
.treasure-content {
padding: 16px 0 10px;
}
.team-container {
margin: 0 10px 12px;
}
.activity-end__desc {
margin: 118px 0 0;
font-size: 30px;
color: #fff;
text-align: center;
line-height: 42px;
}
.team-empty__icon {
display: block;
width: 56px;
height: 49px;
margin: 118px auto 18px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-empty.png');
}
.team-empty__desc {
margin: 0 70px;
font-size: 15px;
color: #fff;
text-align: center;
line-height: 21px;
}
.team-empty__button {
display: block;
width: 297px;
height: 44px;
margin: 20px auto 0;
border: 1px solid #090909;
border-radius: 5px;
box-sizing: border-box;
font-size: 16px;
color: #090909;
background-color: #FFE319;
}
.activity-rule__header {
display: flex;
align-items: center;
justify-content: center;
margin: 49px 0 0;
}
.activity-rule__title {
margin: 0 16px;
font-size: 18px;
color: #FFE300;
line-height: 1;
}
.activity-rule__decorate {
display: inline-block;
width: 11px;
height: 12px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-decorate-0.png');
}
.activity-rule__body {
margin: 13px 0 0;
padding: 0 21px 40px;
p {
font-size: 12px;
color: #FFE300;
line-height: 18px;
}
}
}
// 所有弹窗
.popup-container {
&.year {
.close-icon {
position: absolute;
bottom: 80px;
left: 0;
right: 0;
margin: 0 auto;
}
}
}
// 地址弹窗--宝箱
.address-treasure__desc {
margin: 12px 0 0;
font-size: 14px;
color: #666;
line-height: 1;
}
.address-treasure__notice {
margin: 10px 0 16px;
font-size: 12px;
color: #FF2121;
line-height: 1;
}
// 绑定手机弹窗--宝箱
.phone-treasure__desc {
width: 269px;
margin: 10px 25px 0;
font-size: 14px;
color: #666;
line-height: 1;
}
.phone-treasure__notice {
width: 269px;
margin: 9px 25px 15px;
font-size: 12px;
color: #FF2121;
line-height: 18px;
}
\ No newline at end of file
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './mask.scss';
const Root = document.querySelector('body');
class Mask extends Component {
constructor(props) {
super(props);
if(!this.el) {
this.el = document.createElement('div');
}
}
componentDidMount() {
Root.appendChild(this.el);
}
componentWillUnmount() {
Root.removeChild(this.el);
}
render() {
const { visible, handleToHide } = this.props;
if(visible) {
return ReactDOM.createPortal(
(
<div className="mask">
<div className="mask-content">
{this.props.children}
</div>
<div className="mask-footer">
<i className="mask-button__close" onClick={handleToHide}></i>
</div>
</div>
),
this.el
);
}else {
return null;
}
}
}
export default Mask;
\ No newline at end of file
.mask {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
color:#fff;
background-color: rgba(0, 0, 0, .5);
}
.mask-content {
min-width: 200px;
min-height: 100px;
padding: 10px 0;
border-radius: 5px;
box-sizing: border-box;
background-color: #fff;
}
.mask-footer {
margin-top: 33px;
}
.mask-button__close {
display: inline-block;
width: 33px;
height: 33px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/close-btn.png');
}
\ No newline at end of file
import React from 'react';
import './prize.scss';
export default (props) => {
const {
data: {
bind_phone,
bind_address,
prize_type,
},
handleToBindPhone,
handleToBindAddress,
toComposeCoupon,
toUseCoupon,
toCourseList,
toFecthMoney,
} = props;
return (
<>
{/* 第一:是否需要绑定手机号 */}
{
bind_phone &&
<a className="team-result" onClick={handleToBindPhone}>
<span>绑定手机号</span>
</a>
}
{/* 第二:是否需要填写地址 */}
{
(!bind_phone && bind_address) &&
<a className="team-result" onClick={handleToBindAddress}>
<span>查看/修改收货信息</span>
</a>
}
{/* 第三:奖品,实物 */}
{
(!bind_phone && !bind_address && prize_type === 1) &&
<a className="team-result" onClick={handleToBindAddress}>
<span>查看/修改收货信息</span>
</a>
}
{/* 第三:奖品,代金券碎片 */}
{
(!bind_phone && !bind_address && prize_type === 6) &&
<a className="team-result" onClick={toComposeCoupon}>
可合成代金券在购课时使用,
<span>去合成</span>
</a>
}
{/* 第三:奖品,指定课程代金券 */}
{
(!bind_phone && !bind_address && prize_type === 3) &&
<a className="team-result" onClick={toUseCoupon}>
已发放至您的账户,
<span>去使用</span>
</a>
}
{/* 第三:奖品,通用课程代金券 */}
{
(!bind_phone && !bind_address && prize_type === 4) &&
<a className="team-result" onClick={toCourseList}>
已发放至您的账户,
<span>去使用</span>
</a>
}
{/* 第三:奖品,现金红包 */}
{
(!bind_phone && !bind_address && prize_type === 7) &&
<a className="team-result" onClick={toFecthMoney}>
已存入您的账户,
<span>去提现</span>
</a>
}
{/* 第三:奖品,线上课程 */}
{
(!bind_phone && !bind_address && prize_type === 2) &&
<a className="team-result">已发放至您的账户</a>
}
{/* 第三:奖品,任意线上课程兑换券 */}
{
(!bind_phone && !bind_address && prize_type === 5) &&
<a className="team-result">文案待定</a>
}
</>
)
}
\ No newline at end of file
.team-result {
display: inline-block;
margin: 8px 0 0;
font-size: 12px;
color: #666;
text-align: center;
line-height: 1;
span {
text-decoration: underline;
}
}
\ No newline at end of file
import React, { Component } from 'react';
import classnames from 'classnames';
import { Link } from 'react-router-dom';
import './team.scss';
class TreasureTeam extends Component {
constructor(props) {
super(props);
this.state = {
team: {},
currentMember: {}
};
}
componentDidMount() {
this.initMemberInfo();
}
componentWillReceiveProps(nextProps) {
const { data: oldData } = this.props;
const { data: newData } = nextProps;
if(newData.is_open != oldData.is_open) {
this.initMemberInfo(newData);
}
}
initMemberInfo = (params = {}) => {
const { data, userInfo } = this.props;
const arr = JSON.stringify(params) !== '{}'? params: data;
let member = arr.member;
let len = member.length - 5;
for(; len < 0; len++) {
member.push({});
}
this.setState({
team: Object.assign({}, arr, {
member
}),
currentMember: userInfo.uid? member.filter(item => item.uid == userInfo.uid)[0] : {}
});
}
computedClass = (id) => {
const { data: { is_open } } = this.props;
const { currentMember } = this.state;
return classnames(
'team-member__item',
{
'active': id === currentMember.uid && is_open,
}
);
}
computedBg = (val) => {
return val? {
backgroundImage: `url(${val})`
} : {};
}
// 查看队友的奖品,条件:宝箱已拆
toCheckPrize = (id) => {
const { team: { is_open, member = []} } = this.state;
if(is_open) {
const data = member.filter(item => item.uid === id);
this.setState({
currentMember: data[0]
});
}
}
render() {
const {
team: {
is_captain,
status,
team_num,
lack_member,
is_open,
treasure_code,
member = [],
},
currentMember
} = this.state;
const {
toSplitTreasure,
userInfo,
children
} = this.props;
return (
<div className="team-container" data-skip="team">
{
!is_captain &&
<i className="team-friend"></i>
}
{/* 组队状态 */}
{
status === 1
? <i className="team-status">组队中..</i>
: <i className="team-decorate"></i>
}
{/* 队伍类型 */}
{
is_captain
? <h2 className="team-title">{team_num}号队伍</h2>
: <h2 className="team-title">好友队伍</h2>
}
{/* 队员情况 */}
{
status === 1
? <p className="team-desc">还差{lack_member}名队员即可获得宝箱哦~</p>
: <p className="team-desc">组队成功</p>
}
<div className="team-member">
{
member.map((item, index) => (
<div
className={this.computedClass(item.uid)}
onClick={() => this.toCheckPrize(item.uid)}
key={index}
style={this.computedBg(item.head_img)}
>
{
item.is_captain &&
<span className="team-member__captain">队长</span>
}
</div>
))
}
</div>
<div className="team-footer" data-layout={is_open? 'column': 'row'}>
{/* 队伍未满 */}
{
status === 1 &&
<>
{
is_captain
? <Link className="team-button" to={`/activity/newyear-2019/landing?treasure_code=${treasure_code}&origin=1`}>继续邀请队友</Link>
: <Link className="team-button" to={`/activity/newyear-2019/landing?treasure_code=${treasure_code}&origin=2`}>帮好友完成组队</Link>
}
</>
}
{/* 可拆状态 */}
{
(status === 2 && !is_open) &&
<>
<span className="team-icon" data-direction="left"></span>
<span className="team-button--split" onClick={toSplitTreasure}></span>
<span className="team-icon" data-direction="right"></span>
</>
}
{/* 已拆状态 */}
{
(status === 2 && is_open) &&
<>
{
currentMember.prize_name
? <p className="team-prize">{currentMember.prize_name}</p>
: <p className="team-prize">尚未开宝箱</p>
}
{
currentMember.uid == userInfo.uid
? children
: null
}
</>
}
</div>
</div>
)
}
}
export default TreasureTeam;
\ No newline at end of file
.team-container {
&[data-skip="team"] {
height: 195px;
border-radius: 3px;
box-sizing: border-box;
background-color: #fff;
}
}
[data-skip="team"] {
position: relative;
padding: 10px 0 0;
.team-friend {
position: absolute;
top: 0;
left: 0;
width: 22px;
height: 22px;
padding-left: 2px;
box-sizing: border-box;
font-size: 12px;
font-style: normal;
color: #fff;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/team-friend-bg.png');
}
.team-status {
position: absolute;
top: 0;
right: 0;
width: 54px;
border-radius: 0 3px 0 5px;
font-size: 12px;
font-style: normal;
color: #fff;
text-align: center;
line-height: 24px;
background-color: #00C091;
}
.team-decorate {
position: absolute;
top: -10px;
right: -10px;
width: 25px;
height: 25px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/team-decorate.png');
}
.team-title {
margin: 5px 0 0;
font-size: 16px;
color: #090909;
text-align: center;
line-height: 1;
}
.team-desc {
margin: 10px 0 0;
font-size: 12px;
color: #FF2121;
text-align: center;
line-height: 1;
}
.team-member {
display: flex;
align-items: center;
justify-content: center;
margin: 18px 0 0;
}
.team-member__item {
position: relative;
width: 44px;
height: 44px;
margin: 0 10px;
border-radius: 50%;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/team-bg.png');
&.active {
border: 1px solid #00C091;
&::after {
display: block;
}
}
&::after {
content: '';
display: none;
position: absolute;
left: 0;
bottom: -12px;
right: 0;
width: 24px;
height: 3px;
margin: 0 auto;
border-radius: 50%;
background-color: #E6E6E6;
}
}
.team-member__captain {
position: absolute;
top: -6px;
right: -23px;
width: 33px;
height: 18px;
border-radius: 9px 9px 9px 1px;
border: 1px solid #fff;
box-sizing: border-box;
font-size: 12px;
color: #0B7B45;
text-align: center;
line-height: 18px;
background-color: #FFE319;
}
.team-footer {
display: flex;
align-items: center;
justify-content: center;
margin: 17px 0 0;
&[data-layout="column"] {
flex-direction: column;
}
}
.team-button {
display: block;
width: 297px;
height: 44px;
margin: 0 auto;
border: 1px solid #090909;
border-radius: 5px;
box-sizing: border-box;
font-size: 16px;
color: #090909;
text-align: center;
line-height: 44px;
background-color: #FFE319;
}
.team-button--split {
display: inline-block;
width: 60px;
height: 46px;
margin: 0 20px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/treasure-box.png');
}
.team-icon {
display: inline-block;
width: 31px;
height: 21px;
background-size: cover;
&[data-direction="left"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-direction-left.png');
}
&[data-direction="right"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-direction-right.png');
}
}
.team-prize {
margin: 5px 0 0;
font-size: 15px;
color: #303030;
line-height: 1;
}
.team-result {
margin: 8px 0 0;
font-size: 12px;
color: #666;
line-height: 1;
span {
text-decoration: underline;
}
}
}
\ No newline at end of file
import React, { Component } from 'react';
import './index.scss';
import { Toast } from 'antd-mobile';
import {Link, withRouter} from "react-router-dom"
import { getParam, http, SendMessageToApp, browser } from "@/utils"
import CommonContainer from './../../common/commonContainer/index'
import CommonPopup from './../../common/commonPopup/index';
import { connect } from 'react-redux';
import { Popup } from "@common/index"
import QRCode from 'qrcode'
@connect(state => ({
user: state.user
}))
class LiveRoom extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
showMark: false,
subUrl: '',
}
}
componentDidMount() {
this.getLiveInfo();
}
getLiveInfo = () => {
http.get(`${API.home}/activity/get_live_info`).then(res => {
const { code, data, msg } = res.data;
if (code === 200) {
this.setState({
list: data
})
} else {
Toast.info(msg);
}
});
}
// 预约直播
subscribe = (id) => {
// 检查是否已登录
const {hasError, data = {}} = this.props.user;
if(hasError) {
this.toLogin();
}else{
http.get(`${API['base-api']}/sys/createLiveQrcode/${id}`).then(res => {
let { errno, data, msg } = res.data;
if (errno === 200) {
QRCode.toDataURL(data.url, (err, url) => {
this.setState({
showMark: true,
subUrl: url,
})
})
} else {
Toast.info(msg);
}
});
}
}
// 已预约 给提示
tip = () => {
Toast.info('你已预约该直播');
}
// 去直播间
toLivingRoom = (id) => {
const {hasError, data = {}} = this.props.user;
if(hasError) {
this.toLogin();
}else{
window.location.href = `${window.location.protocol}//www.julyedu.com/live/m_room/${id}`
}
}
// 查看回放
checkVideo = (url) => {
const {hasError, data = {}} = this.props.user;
if(hasError) {
this.toLogin();
}else{
const vCourseId = url.split('/')[0];
history.push(`/play/video?id=${vCourseId}`)
}
}
// 关闭弹框
closePopup = () => {
this.setState({
showMark: false,
})
// 关闭弹框的时候再次查询接口 查询预约状态
this.getLiveInfo();
}
// APP内需要保存图片 是否还是这样做 需要确认
saveImage = () => {
let version = getParam('version')
version = typeof version === 'string' ? version.replace('.', '').replace('.', '').slice(0, 3) : ''
const {QRCodeUrl} = this.state
if (version && parseInt(version) < 451) {
Toast.info('当前不支持此功能,升级到最新版本app可以点击保存二维码!', 2, null, false)
} else {
SendMessageToApp('generateQRCode', QRCodeUrl)
}
}
// 去登录
toLogin = () => {
if (!getParam('version')) {
this.props.history.push('/passport/login')
} else {
SendMessageToApp("toLogin")
}
}
render() {
const { list,showMark,subUrl } = this.state;
return (
<div className='live__container'>
{
showMark && (
<CommonPopup top={50} closePopup={this.closePopup} mark={true}>
<div className='sub__code_container'>
<p className='sub__title'>扫码关注“七月在线”服务号即可预约</p>
<img className='sub__qr_code' id={'live-qr-code'} src={subUrl} alt=""/>
{
browser.isAndroidApp ? (
<button className={'save-image'} onClick={this.saveImage}>保存二维码</button>
) : null
}
</div>
</CommonPopup>
)
}
<CommonContainer title='大咖直播' id="year-live">
<ul className='live__list'>
{
list.length && (
list.map((item, index) => {
return <li key={index} className='live_room_item'>
<img className='user__avatar' src={item.avatar} alt="" />
<div className='live__info'>
<div className="theme">
<span>主题:</span>
<p>{item.title}</p>
</div>
<div className="info__item">
<span>时间:</span>
<p>{item.date}</p>
</div>
<div className="info__item">
<span>讲师:</span>
<p>{item.teacher}</p>
</div>
{
item.on_live == 0 && item.is_end == 0 && item.is_subscribe == 0 && (
<span onClick={ ()=>this.subscribe(item.live_id)} className="order__btn">立即预约</span>
)
}
{
item.on_live == 0 && item.is_end == 0 && item.is_subscribe == 1 && (
<span onClick={this.tip} className="order__btn subscribed">已预约</span>
)
}
{
item.on_live == 1 && item.is_end == 0 && (
<span onClick={()=>this.toLivingRoom(item.room_url)} className="order__btn living">正在直播</span>
)
}
{
item.is_end == 1 && item.transcribe_url != '' && (
<span onClick={() => this.checkVideo(item.transcribe_url)} className="order__btn check__video">查看回放</span>
)
}
</div>
</li>
})
)
}
</ul>
</CommonContainer>
</div>
)
}
}
export default withRouter(LiveRoom)
.live__container {
.live_room_item {
width: 330px;
height: 100px;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
padding-bottom: 15px;
margin-top: 15px;
&:first-child {
border-bottom: 1px solid rgba(13, 77, 43, 1);
}
.user__avatar {
width: 73px;
height: 85px;
flex: 0 0 auto;
margin-right: 12px;
background: #ddd;
border-radius: 4px;
}
.live__info {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
color: #fff;
font-size: 14px;
width: 246px;
height: 85px;
position: relative;
.info__item {
display: flex;
justify-content: flex-start;
align-content: center;
&:nth-child(2) {
margin: 9px 0;
}
span {
width: 46px;
flex: 0 0 auto;
color: #eaf787;
line-height: 16px;
}
p {
line-height: 16px;
}
}
.theme {
span {
display: block;
width: 46px;
float: left;
color: #eaf787;
line-height: 16px;
}
p {
width: 198px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
float: left;
line-height: 16px;
color: #fff;
/* autoprefixer: off */
-webkit-box-orient: vertical;
}
}
.order__btn {
position: absolute;
right: 0;
bottom: 0;
width: 89px;
height: 28px;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
color: #070f08;
background: linear-gradient(
90deg,
rgba(255, 227, 0, 1) 0%,
rgba(255, 202, 0, 1) 100%
);
}
.subscribed {
background: rgba(254, 228, 29, 1);
}
.living {
background: rgba(0, 153, 255, 1);
color: #fff;
}
.check__video {
background: rgba(114, 220, 141, 1);
color: #fff;
}
}
}
.sub__code_container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.sub__title {
color: #525c65;
font-size: 16px;
line-height: 16px;
font-weight: 500;
text-align: center;
margin: 20px 0;
}
}
.save-image {
margin-top: 16px;
width: 270px;
height: 44px;
background: rgba(255, 227, 25, 1);
border: 1px solid rgba(9, 9, 9, 1);
border-radius: 5px;
font-size: 16px;
font-weight: normal;
color: rgba(9, 9, 9, 1);
}
}
import React, {Component} from 'react'
import './index.scss'
import {http, SendMessageToApp, getParam, browser} from '@/utils'
import CommonContainer from './../../common/commonContainer/index'
import CourseItem from '../../../../blessingPreheat/courseItem/index'
import {withRouter} from "react-router-dom"
import CommonPopup from './../../common/commonPopup/index'
import {Toast} from 'antd-mobile'
import QRCode from 'qrcode'
import {connect} from "react-redux"
@connect(state => ({
user: state.user
}))
class YearCourse extends Component {
constructor(props) {
super(props)
this.state = {
tofreeStudy: false,
basic: {
course: [],
courseList: [],
isMore: false,
addshowMore: false,
},
advanced: {
course: [],
courseList: [],
isMore: false,
addshowMore: false,
},
higher: {
course: [],
courseList: [],
isMore: false,
addshowMore: false,
},
expand: {
course: [],
courseList: [],
isMore: false,
addshowMore: false,
},
bigcourse: {
course: [],
courseList: [],
isMore: false,
},
freecourse: {
course: [],
courseList: [],
isMore: false,
},
groupcourse: {
course: [],
courseList: [],
isMore: false,
},
isshowFollow: false, // 是否提示关注公众号
wish: {
id: '',
key: ""
},
followBarcode: '',
sum:'',
removable:'',
currentId:''
}
}
componentDidMount() {
this.getTeamInfo()
this.getLength()
this.fetchBigCourse()
this.fetchFreeCourse()
this.fetchGroupCourse()
// AI之路-基础
this.fetchAICourse('one', false)
// AI之路-进阶
this.fetchAICourse('two', false)
// AI之路-高阶
this.fetchAICourse('three', false)
// AI之路-拓展
this.fetchAICourse('four', false)
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
if (this.props.isAppUpdate !== nextProps.isAppUpdate) {
this.fetchBigCourse()
this.fetchFreeCourse()
this.fetchGroupCourse()
// AI之路-基础
this.fetchAICourse('one')
// AI之路-进阶
this.fetchAICourse('two')
// AI之路-高阶
this.fetchAICourse('three')
// AI之路-拓展
this.fetchAICourse('four')
return false
}
return true
}
getLength = () => {
let _this = this
http.get(`${API.home}/activity/wish_sum`).then(res => {
const {code, data} = res.data
if (code == 200) {
_this.setState({
sum: data.sum
})
}
})
}
fetchBigCourse = () => {
const {bigcourse} = this.state
http.get(`${API.home}/activity/preheat_data`).then(res => {
const {code, data} = res.data
if (code === 200) {
this.setState({
bigcourse: Object.assign({}, bigcourse, {
isMore: data.length > 4 ? true : false,
course: data.length > 4 ? data.filter((item, index) => index < 4) : data,
courseList: data,
})
})
}
})
}
fetchFreeCourse = () => {
const {freecourse} = this.state
http.get(`${API['base-api']}/assistance/detail`).then(res => {
const {errno, data} = res.data
if (errno === 200) {
this.setState({
freecourse: Object.assign({}, freecourse, {
isMore: data.course_info.length > 4 ? true : false,
course: data.course_info.length > 4 ? data.course_info.filter((item, index) => index < 4) : data.course_info,
courseList: data.course_info,
})
})
}
})
}
fetchGroupCourse = () => {
const {groupcourse} = this.state
http.get(`${API.home}/activity/excellent_course`).then(res => {
const {code, data} = res.data
if (code === 200) {
this.setState({
groupcourse: Object.assign({}, groupcourse, {
isMore: data.length > 4 ? true : false,
course: data.length > 4 ? data.filter((item, index) => index < 4) : data,
courseList: data,
})
})
}
})
}
fetchAICourse = (key, addshowMore) => {
http.get(`${API.home}/activity/four_stage/${key}`).then(res => {
const {code, data} = res.data
if (code === 200) {
this.getList(key, data, addshowMore)
}
})
}
getList = (key, data, addshowMore) => {
const {basic, advanced, higher, expand} = this.state
if (key === 'one') {
this.setState({
basic: Object.assign({}, basic, {
isMore: data.length > 4 && !addshowMore ? true : false,
course: data.length > 4 && !addshowMore ? data.filter((item, index) => index < 4) : data,
courseList: data,
addshowMore: addshowMore,
})
})
}
if (key === 'two') {
this.setState({
advanced: Object.assign({}, advanced, {
isMore: data.length > 4 && !addshowMore ? true : false,
course: data.length > 4 && !addshowMore ? data.filter((item, index) => index < 4) : data,
courseList: data,
addshowMore: addshowMore,
})
})
}
if (key === 'three') {
this.setState({
higher: Object.assign({}, higher, {
isMore: data.length > 4 && !addshowMore ? true : false,
course: data.length > 4 && !addshowMore ? data.filter((item, index) => index < 4) : data,
courseList: data,
addshowMore: addshowMore,
})
})
}
if (key === 'four') {
this.setState({
expand: Object.assign({}, expand, {
isMore: data.length > 4 && !addshowMore ? true : false,
course: data.length > 4 && !addshowMore ? data.filter((item, index) => index < 4) : data,
courseList: data,
addshowMore: addshowMore,
})
})
}
}
toQQque = () => {
if (!getParam('version')) {
location.href = 'https://q.url.cn/AB8aue?_type=wpa&qidian=true'
} else {
SendMessageToApp("toQQ", 'https://q.url.cn/AB8aue?_type=wpa&qidian=true')
}
}
// 去课程详情页
toCourse = (courseId) => {
const {history} = this.props
if (!getParam('version')) {
history.push(`/detail?id=${courseId}`)
} else {
SendMessageToApp("toCourse", courseId)
}
}
handleToMore = (key) => {
let data = {}
if (this.state[key]['isMore']) {
data[key] = {
isMore: !this.state[key]['isMore'],
course: this.state[key]['courseList'],
courseList: this.state[key]['courseList'],
addshowMore: !this.state[key]['addshowMore']
}
this.setState({
...data
})
} else {
data[key] = {
isMore: !this.state[key]['isMore'],
course: this.state[key]['courseList'].filter((item, index) => index < 4),
courseList: this.state[key]['courseList'],
addshowMore: !this.state[key]['addshowMore']
}
this.setState({
...data
})
}
}
// 去登录
toLogin = () => {
if (!getParam('version')) {
this.props.history.push('/passport/login')
} else {
SendMessageToApp("toLogin")
}
}
// 免费学习
freeStudy = () => {
this.setState({
tofreeStudy: true,
})
}
// 关闭弹框
closePopup = () => {
this.setState({
tofreeStudy: false,
})
}
closePopupWish = () => {
const _this = this
_this.setState({
isshowFollow: false
})
setTimeout(function () {
_this.toJoinList(_this.state.wish.id, _this.state.wish.key)
}, 200)
}
getQRcodeUrl = () => {
let _this = this
http.get(`${API['base-api']}/wx/user_temporary_qrcode/${_this.props.user.data.uid}`)
.then(res => {
const {errno, data, msg} = res.data
QRCode.toDataURL('http://weixin.qq.com/q/02mntn9j4xcw01_VSN1tc2', (err, url) => {
this.setState({
followBarcode: url,
})
})
// _this.followBarcode = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQEV8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAybW50bjlqNHhjdzAxX1ZTTjF0YzIAAgR5pfBdAwSAUQEA"
// if (errno == 0) {
// _this.followBarcode = data.url
// } else {
// Message.warning(msg)
// }
})
}
// 点击加入心愿单登录验证,在判断是否关注公众号,已关注的话直接加入,未关注弹出二维码弹窗,点击关闭按钮加入心愿单
addWishList = (id, key) => {
const _this = this
const isLogin = !this.props.user.hasError
_this.setState({
wish: {
id: id,
key: key
}
})
if (isLogin) {
_this.isFollow(id, key)
} else {
_this.toLogin()
}
}
isFollow = (id, key) => {
const _this = this
http.get(`${API.home}/sys/user/isFollowWeChat`).then(res => {
const {code, data, msg} = res.data
if (code === 200) {
_this.setState({
isshowFollow: !data.is_follow
})
if (!_this.state.isshowFollow) {
_this.toJoinList(id, key)
} else {
_this.getQRcodeUrl()
}
} else {
Toast.info(msg, 2)
}
})
}
toJoinList = (id, key) => {
const _this = this
http.post(`${API.home}/activity/join_list`, {course_id: id})
.then(res => {
const {code, msg} = res.data
if (code == 200) {
Toast.success('已成功加入心愿单', 3)
_this.getLength()
if (key === '1') {
_this.fetchAICourse('one', _this.state.basic.addshowMore)
}
if (key === '2') {
_this.fetchAICourse('two', _this.state.advanced.addshowMore)
}
if (key === '3') {
_this.fetchAICourse('three', _this.state.higher.addshowMore)
}
if (key === '4') {
_this.fetchAICourse('four', _this.state.expand.addshowMore)
}
if (key === 'group') {
_this.fetchGroupCourse()
}
} else {
Toast.info(msg, 2)
}
})
}
// 安卓手机保存二维码
saveImage = () => {
let version = getParam('version')
version = typeof version === 'string' ? version.replace('.', '').replace('.', '').slice(0, 3) : ''
const QRCodeUrl = '//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018christyear/h5/qrcode.jpg'
if (version && parseInt(version) < 451) {
Toast.info('当前不支持此功能,升级到最新版本app可以点击保存二维码!', 3, null, false)
} else {
SendMessageToApp('generateQRCode', QRCodeUrl)
}
}
// 获取队伍信息
getTeamInfo = () => {
http.get(`${API.home}/sys/treasure/teamInfo`).then(res => {
const {code, data, msg} = res.data
if (code === 200) {
const {info, removable_data} = data
this.setState({
removable: info.removable,
currentId: info.removable > 0 ? removable_data[0].id : null
})
} else {
Toast.info(msg)
}
})
}
// 跳转到我的宝箱列表页
toBoxList = () => {
const isLogin = !this.props.user.hasError
const {currentId} = this.state
let search = ''
if (currentId) {
search = `?id=${currentId}`
}
if (isLogin) {
this.props.history.push(`/year/yearTreasure${search}`)
} else {
this.toLogin()
}
}
toYearWish = () => {
const isLogin = !this.props.user.hasError
if (isLogin) {
this.props.history.push('/year/yearWish')
} else {
this.toLogin()
}
}
render() {
const {bigcourse, freecourse, groupcourse, basic, advanced, higher, expand,removable,sum} = this.state
return (
<div className={'year-index-course'}>
{/*浮框*/}
<div className='nav-right'>
<span onClick={this.toBoxList} className='nav-right__link'>
未开宝箱
{
removable > 0 &&
<i className="nav-right__number">{removable}</i>
}
</span>
<a onClick={() => this.toYearWish()} className='nav-right__link'>
心愿单
{
sum > 0 &&
<i className="nav-right__number">{sum}</i>
}
</a>
</div>
<CommonContainer title='重磅好课' id='year-course'>
<div>
{
(bigcourse.course && bigcourse.course.length > 0) &&
<>
<div className='bigcourse course-box'>
{
bigcourse.course.map(item => (
<CourseItem image={item.image_name} key={item.course_id} id={item.course_id}
toCourse={this.toCourse}>
<div className="coupon-course__footer">
{
item.is_buy == 1 &&
<a onClick={() => this.toCourse(item.course_id)} className="btn to-study">开始学习</a>
}
{
item.is_buy == 0 &&
<a onClick={() => this.toQQque()}
className="btn big-course">速抢拼团名额</a>
}
</div>
</CourseItem>
))
}
</div>
{
(bigcourse.courseList && bigcourse.courseList.length > 4) &&
<button className="more-button" onClick={() => this.handleToMore('bigcourse')}>
{group.isMore ? '查看更多' : '收起'}
</button>
}
</>
}
</div>
</CommonContainer>
<CommonContainer title='人气好课免费学' id='year-free'>
<div>
{
(freecourse.course && freecourse.course.length > 0) &&
<>
<div className='freecourse course-box'>
{
freecourse.course.map(item => (
<CourseItem image={item.image_name} key={item.course_id} id={item.course_id}
toCourse={this.toCourse}>
<div className="coupon-course__footer">
{
item.is_buy == 1 &&
<a onClick={() => this.toCourse(item.course_id)} className="btn to-study">开始学习</a>
}
{
item.is_buy == 0 &&
<a onClick={() => this.freeStudy()}
className="btn free-study">点击免费学</a>
}
<p className="free-course-num">已送出<span>{item.act_num}</span>个课程</p>
</div>
</CourseItem>
))
}
</div>
{
(freecourse.courseList && freecourse.courseList.length > 4) &&
<button className="more-button" onClick={() => this.handleToMore('freecourse')}>
{group.isMore ? '查看更多' : '收起'}
</button>
}
</>
}
</div>
</CommonContainer>
<CommonContainer title='精品好课1分开抢' id='year-group'>
<div>
{
(groupcourse.course && groupcourse.course.length > 0) &&
<>
<div className='groupcourse course-box'>
{
groupcourse.course.map(item => (
<CourseItem image={item.image_name} key={item.course_id} id={item.course_id}
toCourse={this.toCourse}>
<div className="group-num">限量300</div>
<div className="coupon-course__footer">
{
item.is_buy == 1 &&
<>
<p className={'course-title text-overflow-1'}>{item.course_title}</p>
<a onClick={() => this.toCourse(item.course_id)}
className="btn to-study">开始学习</a>
</>
}
{
item.is_buy == 0 &&
<>
<div className="type">
<span className="tag">拼团价</span>
<span className="time">1223日开团</span>
</div>
<div className="price">¥
<span className="new-price">0.01</span>
<span
className="old-price">现价:<s>¥{item.price1}</s></span>
</div>
<div className="status">
<a onClick={() => this.toCourse(item.course_id)}
className="status-btn to-buy">直接购买</a>
{
item.is_join == 1 &&
<a className="status-btn add-wish"><img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/add-success.png"
alt=""/>已加心愿单</a>
}
{
item.is_join == 0 &&
<a
onClick={() => this.addWishList(item.course_id, 'group')}
className="status-btn add-wish-success">
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/like_icon.png"
alt=""/>加入心愿单
</a>
}
</div>
</>
}
</div>
</CourseItem>
))
}
</div>
{
(groupcourse.courseList && groupcourse.courseList.length > 4) &&
<button className="more-button" onClick={() => this.handleToMore('groupcourse')}>
{group.isMore ? '查看更多' : '收起'}
</button>
}
</>
}
</div>
</CommonContainer>
<CommonContainer title='好课价到,等你抄底' id='year-discount'>
<div>
<h4 className="ai-course__subtitle">基础</h4>
{
(basic.course && basic.course.length > 0) &&
<>
<div className='groupcourse course-box'>
{
basic.course.map(item => (
<CourseItem image={item.image_name} key={item.course_id} id={item.course_id}
toCourse={this.toCourse}>
<div className="coupon-course__footer">
{
item.is_buy == 1 &&
<>
<p className={'course-title text-overflow-1'}>{item.course_title}</p>
<a onClick={() => this.toCourse(item.course_id)}
className="btn to-study">开始学习</a>
</>
}
{
item.is_buy == 0 &&
<>
<div className="type">
{
item.type == 0 &&
<>
<span className="tag">活动价</span>
<span className="time">12.23开始</span>
</>
}
{
item.type == 1 &&
<>
<span className="tag">拼团价</span>
<span className="time">12.23开团</span>
</>
}
{
item.type == 2 &&
<>
<span className="tag">好友帮帮砍</span>
<span className="time">12.23开砍</span>
</>
}
</div>
<div className="price">
{item.type == 2 ? '到手最低:¥' : '¥'}
<span className="new-price">{item.price2}</span>
<span
className="old-price">
{item.type == 2 ? '' : '现价:'}
<s>¥{item.price1}</s></span>
</div>
<div className="status">
<a onClick={() => this.toCourse(item.course_id)}
className="status-btn to-buy">直接购买</a>
{
item.is_join == 1 &&
<a className="status-btn add-wish"><img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/add-success.png"
alt=""/>已加心愿单</a>
}
{
item.is_join == 0 &&
<a
onClick={() => this.addWishList(item.course_id, '1')}
className="status-btn add-wish-success">
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/like_icon.png"
alt=""/>加入心愿单
</a>
}
</div>
</>
}
</div>
</CourseItem>
))
}
</div>
{
(basic.courseList && basic.courseList.length > 4) &&
<button className="more-button" onClick={() => this.handleToMore('basic')}>
{basic.isMore ? '查看更多' : '收起'}
</button>
}
</>
}
<h4 className="ai-course__subtitle">进阶</h4>
{
(advanced.course && advanced.course.length > 0) &&
<>
<div className='groupcourse course-box'>
{
advanced.course.map(item => (
<CourseItem image={item.image_name} key={item.course_id} id={item.course_id}
toCourse={this.toCourse}>
<div className="coupon-course__footer">
{
item.is_buy == 1 &&
<>
<p className={'course-title text-overflow-1'}>{item.course_title}</p>
<a onClick={() => this.toCourse(item.course_id)}
className="btn to-study">开始学习</a>
</>
}
{
item.is_buy == 0 &&
<>
<div className="type">
{
item.type == 0 &&
<>
<span className="tag">活动价</span>
<span className="time">12.23开始</span>
</>
}
{
item.type == 1 &&
<>
<span className="tag">拼团价</span>
<span className="time">12.23开团</span>
</>
}
{
item.type == 2 &&
<>
<span className="tag">好友帮帮砍</span>
<span className="time">12.23开砍</span>
</>
}
</div>
<div className="price">
{item.type == 2 ? '到手最低:¥' : '¥'}
<span className="new-price">{item.price2}</span>
<span
className="old-price">
{item.type == 2 ? '' : '现价:'}
<s>¥{item.price1}</s></span>
</div>
<div className="status">
<a onClick={() => this.toCourse(item.course_id)}
className="status-btn to-buy">直接购买</a>
{
item.is_join == 1 &&
<a className="status-btn add-wish"><img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/add-success.png"
alt=""/>已加心愿单</a>
}
{
item.is_join == 0 &&
<a
onClick={() => this.addWishList(item.course_id, '2')}
className="status-btn add-wish-success">
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/like_icon.png"
alt=""/>加入心愿单
</a>
}
</div>
</>
}
</div>
</CourseItem>
))
}
</div>
{
(advanced.courseList && advanced.courseList.length > 4) &&
<button className="more-button" onClick={() => this.handleToMore('advanced')}>
{advanced.isMore ? '查看更多' : '收起'}
</button>
}
</>
}
<h4 className="ai-course__subtitle">高阶</h4>
{
(higher.course && higher.course.length > 0) &&
<>
<div className='groupcourse course-box'>
{
higher.course.map(item => (
<CourseItem image={item.image_name} key={item.course_id} id={item.course_id}
toCourse={this.toCourse}>
<div className="coupon-course__footer">
{
item.is_buy == 1 &&
<>
<p className={'course-title text-overflow-1'}>{item.course_title}</p>
<a onClick={() => this.toCourse(item.course_id)}
className="btn to-study">开始学习</a>
</>
}
{
item.is_buy == 0 &&
<>
<div className="type">
{
item.type == 0 &&
<>
<span className="tag">活动价</span>
<span className="time">12.23开始</span>
</>
}
{
item.type == 1 &&
<>
<span className="tag">拼团价</span>
<span className="time">12.23开团</span>
</>
}
{
item.type == 2 &&
<>
<span className="tag">好友帮帮砍</span>
<span className="time">12.23开砍</span>
</>
}
</div>
<div className="price">
{item.type == 2 ? '到手最低:¥' : '¥'}
<span className="new-price">{item.price2}</span>
<span
className="old-price">
{item.type == 2 ? '' : '现价:'}
<s>¥{item.price1}</s></span>
</div>
<div className="status">
<a onClick={() => this.toCourse(item.course_id)}
className="status-btn to-buy">直接购买</a>
{
item.is_join == 1 &&
<a className="status-btn add-wish"><img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/add-success.png"
alt=""/>已加心愿单</a>
}
{
item.is_join == 0 &&
<a
onClick={() => this.addWishList(item.course_id, '3')}
className="status-btn add-wish-success">
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/like_icon.png"
alt=""/>加入心愿单
</a>
}
</div>
</>
}
</div>
</CourseItem>
))
}
</div>
{
(higher.courseList && higher.courseList.length > 4) &&
<button className="more-button" onClick={() => this.handleToMore('higher')}>
{higher.isMore ? '查看更多' : '收起'}
</button>
}
</>
}
<h4 className="ai-course__subtitle">扩展</h4>
{
(expand.course && expand.course.length > 0) &&
<>
<div className='groupcourse course-box'>
{
expand.course.map(item => (
<CourseItem image={item.image_name} key={item.course_id} id={item.course_id}
toCourse={this.toCourse}>
<div className="coupon-course__footer">
{
item.is_buy == 1 &&
<>
<p className={'course-title text-overflow-1'}>{item.course_title}</p>
<a onClick={() => this.toCourse(item.course_id)}
className="btn to-study">开始学习</a>
</>
}
{
item.is_buy == 0 &&
<>
<div className="type">
{
item.type == 0 &&
<>
<span className="tag">活动价</span>
<span className="time">12.23开始</span>
</>
}
{
item.type == 1 &&
<>
<span className="tag">拼团价</span>
<span className="time">12.23开团</span>
</>
}
{
item.type == 2 &&
<>
<span className="tag">好友帮帮砍</span>
<span className="time">12.23开砍</span>
</>
}
</div>
<div className="price">
{item.type == 2 ? '到手最低:¥' : '¥'}
<span className="new-price">{item.price2}</span>
<span
className="old-price">
{item.type == 2 ? '' : '现价:'}
<s>¥{item.price1}</s></span>
</div>
<div className="status">
<a onClick={() => this.toCourse(item.course_id)}
className="status-btn to-buy">直接购买</a>
{
item.is_join == 1 &&
<a className="status-btn add-wish"><img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/add-success.png"
alt=""/>已加心愿单</a>
}
{
item.is_join == 0 &&
<a
onClick={() => this.addWishList(item.course_id, '4')}
className="status-btn add-wish-success">
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/like_icon.png"
alt=""/>加入心愿单
</a>
}
</div>
</>
}
</div>
</CourseItem>
))
}
</div>
{
(expand.courseList && expand.courseList.length > 4) &&
<button className="more-button" onClick={() => this.handleToMore('expand')}>
{expand.isMore ? '查看更多' : '收起'}
</button>
}
</>
}
</div>
</CommonContainer>
{
this.state.tofreeStudy &&
<CommonPopup top={100} closePopup={this.closePopup} mark={false}>
<div className='sub__code_container'>
<p className='sub__title'>提醒服务</p>
<p className='sub__tip'>进入服务号回复<i>77</i>免费领取课程</p>
<img className='sub__qr_code' id={'live-qr-code'}
src='//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018christyear/h5/qrcode.jpg' alt=""/>
{
browser.isAndroidApp ? (
<button className={'save-image'} onClick={this.saveImage}>保存二维码</button>
) : <p className='sub__tip'>长按识别/扫码 关注【七月在线】服务号</p>
}
</div>
</CommonPopup>
}
{
this.state.isshowFollow &&
<CommonPopup top={100} closePopup={this.closePopupWish} mark={false}>
<div className='sub__code_container'>
<p className='sub__title'>提醒服务</p>
<p className='sub__tip'>课程开售立即提醒,不错过任何优惠哦!</p>
<img className='sub__qr_code' id={'live-qr-code'}
src={this.state.followBarcode} alt=""/>
{
browser.isAndroidApp ? (
<button className={'save-image'} onClick={this.saveImage}>保存二维码</button>
) : <p className='sub__tip'>长按识别/扫码 关注【七月在线】服务号</p>
}
</div>
</CommonPopup>
}
</div>
)
}
}
export default withRouter(YearCourse)
.year-index-course {
.course-box {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.course-container {
width: 158px;
margin: 15px 0 0 0;
text-align: center;
position: relative;
}
.group-num {
width: 66px;
height: 16px;
position: absolute;
left: 10px;
top: 10px;
line-height: 16px;
background: #CA161C;
opacity: 0.8;
border-radius: 1px;
font-size: 12px;
color: #fff;
text-align: center;
}
.coupon-course__footer {
.course-title {
padding-left: 10px;
font-size: 15px;
color: #333;
font-weight: 500;
margin-top: 7px;
}
.btn {
display: inline-block;
width: 138px;
height: 24px;
text-align: center;
line-height: 24px;
border-radius: 2px;
font-size: 12px;
outline: none;
border: none;
letter-spacing: 1px;
}
.big-course {
background-color: #FEE41D;
border: 1px solid #090F08;
color: #090F08;
margin-top: 10px;
}
.to-study {
background-color: #09f;
color: #fff;
position: absolute;
left: 10px;
bottom: 10px;
}
.free-study {
background: linear-gradient(-90deg, #EB1612 0%, #F92927 100%);
color: #fff;
margin-top: 10px;
}
.free-course-num {
font-size: 12px;
color: #070F08;
margin-top: 7px;
letter-spacing: 1px;
span {
font-size: 14px;
color: #FF0002;
}
}
}
.type {
text-align: left;
padding-left: 7px;
margin-top: 3px;
.tag {
display: inline-block;
padding: 0 6px;
height: 14px;
line-height: 15px;
text-align: center;
font-size: 12px;
color: #FFF;
position: relative;
z-index: 0;
}
.time {
display: inline-block;
height: 15px;
line-height: 15px;
padding: 0 6px;
margin-left: 5px;
position: relative;
font-size: 12px;
color: #555;
text-align: center;
z-index: 0;
}
.time:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #E6E6E6;
transform: skewX(-20deg);
z-index: -1;
}
.tag:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #FF0002;
transform: skewX(-20deg);
z-index: -1;
}
}
.price {
text-align: left;
padding-left: 5px;
margin-top: 3px;
color: #FF0002;
font-size: 12px;
.new-price {
font-size: 18px;
}
.old-price {
font-size: 12px;
color: #666;
margin-left: 8px;
}
}
.status {
text-align: left;
padding-left: 5px;
position: absolute;
bottom: 10px;
.status-btn {
display: inline-block;
height: 22px;
line-height: 22px;
border-radius: 2px;
text-align: center;
font-size: 12px;
color: #fff;
}
.to-buy {
width: 55px;
background-color: #FF8080;
}
.add-wish, .add-wish-success {
width: 88px;
margin-left: 5px;
outline: none;
color: #FF0002;
background-color: #fff;
border: 1px solid #FF0002;
img {
width: 12px;
height: 11px;
margin-right: 2px;
position: relative;
top: 1px;
}
}
.add-wish-success {
color: #fff;
background: linear-gradient(90deg, rgba(235, 22, 18, 1) 0%, rgba(249, 41, 39, 1) 100%);
}
}
}
.bigcourse .course-container {
height: 156px;
}
.freecourse .course-container {
height: 177px;
}
.groupcourse .course-container {
height: 195px;
}
.ai-course__subtitle {
width: 73px;
height: 24px;
margin: 15px auto 0;
border-radius: 12px;
font-size: 14px;
font-weight: 500;
color: #070F08;
text-align: center;
line-height: 22px;
letter-spacing: 2px;
background-color: #FFE300;
border: 1px solid #070F08;
}
.more-button {
display: block;
width: 75px;
height: 26px;
margin: 15px auto 5px;
padding: 0;
border-radius: 12px;
font-size: 12px;
font-weight: 400;
color: #fff;
line-height: 26px;
cursor: pointer;
outline: none;
background-color: #0F6237;
border: none;
letter-spacing: 1px;
}
.sub__code_container {
padding: 20px;
}
.save-image {
display: block;
width: 133px;
height: 30px;
margin: 20px auto 0 auto;
background: rgba(83, 39, 250, 1);
border-radius: 15px;
font-size: 14px;
color: #fff;
-webkit-appearance: none;
outline: 0;
border: none;
}
.nav-right {
width: 100px;
height: 125px;
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/sd_fc_bj.png");
background-repeat: no-repeat;
background-size: cover;
position: fixed;
top: 50%;
right: 0;
margin-top: -57px;
z-index: 22;
.nav-right__link {
display: block;
position: relative;
font-size: 12px;
font-weight: 500;
color: #fff;
text-align: center;
top: 47px;
line-height: 25px;
}
.nav-right__number {
position: absolute;
top: -5px;
right: 5px;
padding: 0 5px;
border: 1px solid #F7D067;
border-radius: 7px 7px 7px 0px;
font-size: 12px;
font-style: normal;
color: #FEE41D;
background-color: #FF4F24;
height: 16px;
line-height: 14px;
}
}
}
\ No newline at end of file
import React, {Component} from 'react'
import './index.scss'
import LiveRoom from './LiveRoom/index'
import YearCourse from './YearCourse/index'
import TreasureBox from './../treasure-box/index'
import TreasureNav from './nav'
import CommonPopup from './../common/commonPopup/index'
import cookie from "js-cookie"
import {setCurrentUser, startFetchUser} from "@/store/userAction"
import {SendMessageToApp, getParam, http} from '@/utils'
import {addDays} from "date-fns"
import {connect} from "react-redux"
import {Toast} from 'antd-mobile'
import {compose} from "redux"
@connect(state => ({
user: state.user
}),
{setCurrentUser, startFetchUser}
)
export default class index extends Component {
state = {
removable: 0, // 未拆宝箱的数量
currentOpenId: 0, // 当前要拆的宝箱的队伍的ID
treasure_stage: 0, // 宝箱的活动阶段
active_stage: 0, // 整个活动的阶段
userInfoList: [],
userInfo: {},
isAppUpdate: false,
showMark: false,
banner: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_banner_bj%402x.png'
}
componentDidMount() {
const _this = this
// 获取App登录信息
window['loginInfo'] = result => {
_this.loginInfo(result)
}
_this.getStage()
}
// 获取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.setState({
isAppUpdate: 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
}
// 关闭弹框
closePopup = () => {
this.setState({
showMark: false,
})
}
// 获取未拆宝箱数量
getRemovable = (removable, currentOpenId) => {
}
// 获取活动以及宝箱的阶段
getStage = () => {
http.get(`${API.home}/activity/stage`).then(res => {
const {code, data, msg} = res.data
if (code === 200) {
// treasure_stage,宝箱阶段,0-不在活动时间,1-活动时间内
this.setState({
treasure_stage: data.treasure_stage
})
} else {
Toast.info(msg, 2)
}
})
}
render() {
const {banner, removable, treasure_stage, currentOpenId} = this.state
return (
<div className={'year-index'}>
<div className="banner-treasure">
<div id="banner" className="banner-treasure__header"
style={{backgroundImage: `url(${banner})`}}></div>
<div className="banner-treasure__nav">
<TreasureNav id="banner" treasure_stage={treasure_stage}/>
</div>
<div className="banner-treasure__decorate"></div>
</div>
{/* 大咖直播 */}
<LiveRoom/>
{/* 组队开宝箱 */}
{
treasure_stage === 1 && <TreasureBox getRemovable={this.getRemovable}/>
}
{/*课程*/}
<YearCourse currentOpenId={currentOpenId} removable={removable} isAppUpdate={this.state.isAppUpdate} />
{/*好友加入队伍提醒;获得宝箱提醒;开售提醒弹窗,需要自取,注意修改文案*/}
{
this.state.showMark &&
<CommonPopup top={50} closePopup={this.closePopup} mark={true}>
<div className='sub__code_container'>
<p className='sub__title'>提醒服务</p>
<p className='sub__tip'>有好友加入队伍后第一时间通知我~</p>
<img className='sub__qr_code' id={'live-qr-code'}
src='//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018christyear/h5/qrcode.jpg' alt=""/>
<p className='sub__tip'>长按识别/扫码 关注【七月在线】服务号即可预约</p>
</div>
</CommonPopup>
}
{/*规则弹窗*/}
{
this.state.showMark &&
<CommonPopup top={50} closePopup={this.closePopup} mark={true}>
<div className='sub__code_container'>
<p className='sub__title'>组队开宝箱活动规则</p>
<p className='sub__rule'>
1. 活动期间(1218-1231日)可随时参与开宝箱;<br/>
2. 当前队伍满员后可继续创建新队伍;<br/>
3. 每人有一次机会加入好友的队伍;<br/>
4. 队伍满员后所有成员均可随机获得宝箱内奖品,队长奖励更丰厚哦~<br/>
5. 代金券、课程等虚拟奖品将直接发放至账户,实物奖品活动结束后统一邮寄;<br/>
6. 现金可提现:我的 赚奖学金 提现。
</p>
</div>
</CommonPopup>
}
</div>
)
}
}
.year-index {
padding-bottom: 30px;
background-color: #BC2A18;
.banner-treasure {
}
.banner-treasure__header {
height: 320px;
background-size: cover;
background-position: center;
}
.banner-treasure__nav {
height: 30px;
}
.banner-treasure__decorate {
height: 35px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_nv_bj%402x.png');
}
.sub__code_container {
padding: 20px 30px;
text-align: center;
.sub__title {
font-size: 18px;
color: #111;
font-weight: normal;
}
.sub__qr_code {
width: 137px;
height: 137px;
}
.sub__tip {
font-size: 14px;
color: #666;
margin: 13px 0;
letter-spacing: 1px;
i {
font-style: normal;
color: #FF0000;
font-size: 16px;
}
}
.sub__rule {
font-size: 14px;
color: #666;
text-align: left;
margin-top: 20px;
margin-bottom: 5px;
}
}
}
.year-index + .year19-index {
display: none;
}
\ No newline at end of file
import React, { Component } from 'react';
import classnames from 'classnames';
import { http } from '@/utils';
import './nav.scss';
class TreasureNav extends Component {
constructor(props) {
super(props);
this.state = {
isFixed: false,
curIndex: 1,
formatNavs: [],
navs: [
{
id: 'year-live',
name: '大咖直播'
},
{
id: 'year-treasure',
name: '组队开宝箱'
},
{
id: 'year-course',
name: '重磅好课'
},
{
id: 'year-free',
name: '免费学'
},
{
id: 'year-group',
name: '1分拼团'
},
{
id: 'year-discount',
name: '抄底专区'
},
]
};
}
componentDidMount() {
window.addEventListener('scroll', this.calcNavActive)
}
componentWillUnmount () {
window.removeEventListener('scroll', this.calcNavActive);
}
componentWillReceiveProps(nextProps) {
this.initNav(nextProps.treasure_stage);
}
initNav = (treasure_stage) => {
let {navs} = this.state;
// treasure_stage,宝箱阶段,0-不在活动时间,1-活动时间内
if(treasure_stage === 0) {
this.setState({
formatNavs: navs.filter(item => item.id !== 'year-treasure')
});
}else {
this.setState({
formatNavs: navs
})
}
}
calcNavActive = () => {
const { formatNavs } = this.state;
const { id } = this.props;
const bannerEl = document.querySelector(`#${id}`);
setTimeout(() => {
let y = window.scrollY,
len = formatNavs.length - 1;
this.setState({
isFixed: y >= bannerEl.offsetHeight
});
for (; len > -1; len--) {
let el = document.querySelector(`#${formatNavs[len].id}`);
if (el && (y + 200) >= el.offsetTop) {
this.setState({
curIndex: len
})
break;
}
}
}, 100);
}
selectToNav = (i) => {
const { formatNavs } = this.state;
const id = `#${formatNavs[i]['id']}`;
let el = document.querySelector(id);
if(el) {
this.setState({
curIndex: i
});
window.scrollTo({
top: el.offsetTop,
left: 0
});
}
}
render() {
const { isFixed, curIndex, formatNavs } = this.state;
return (
<div className={classnames("treasure-nav", {'fixed': isFixed})} data-skip="nav">
{
formatNavs.map((item, index) => (
<a
href={`#${item.id}`}
className={classnames("treasure-nav__item", {'active': index === curIndex})}
key={item.id}
onClick={() => this.selectToNav(index)}
>{item.name}</a>
))
}
</div>
)
}
}
export default TreasureNav;
\ No newline at end of file
.treasure-nav {
&[data-skip="nav"] {
display: flex;
align-items: center;
justify-content: center;
height: 30px;
background-color: #357345;
}
&.fixed {
position: fixed;
top: 0;
width: 100%;
z-index: 999;
}
}
[data-skip="nav"] {
.treasure-nav__item {
flex: 1;
box-sizing: border-box;
font-size: 12px;
color: #fff;
text-align: center;
line-height: 26px;
&.active {
border-right: 1px solid #090F08;
border-radius: 3px;
color: #090F08;
background-color: #FEE41D;
}
}
}
\ No newline at end of file
import React, { Component } from 'react';
import CommonContainer from './../common/commonContainer/index';
import TreasureRank from './rank';
import TeamInfo from './team'
import Prizes from "@components/activity/newyear-2019/common/prizes"
import UserBulletScreen from "@components/activity/newyear-2019/common/user-bullet-screen"
class TreasureBox extends Component {
constructor(props) {
super(props);
}
render() {
return (
<CommonContainer id="year-treasure" title={'组队开宝箱'}>
<div style={{textAlign: 'center', fontSize: '12px', color: '#FFDC1E', marginTop: '10px'}}>邀请好友组队一起开宝箱,满5人后将随机获得以下奖品~</div>
<Prizes showSystemNotices={true}/>
<UserBulletScreen/>
<TeamInfo getRemovable={this.props.getRemovable} />
<TreasureRank />
</CommonContainer>
)
}
}
export default TreasureBox;
import React, { Component } from 'react';
import { http } from '@/utils';
import './rank.scss'
class TreasureRank extends Component {
constructor(props) {
super(props);
this.state = {
rank: [],
rankList: [],
isMore: false,
}
}
componentDidMount() {
this.fetchRankInfo();
}
fetchRankInfo = () => {
http.get(`${API.home}/sys/treasure/ranking`).then(res => {
const { code, data } = res.data;
if(code === 200) {
if(data.length > 5) {
this.setState({
rank: data.filter((item, index) => index < 5),
rankList: data,
isMore: true,
});
}else {
this.setState({
rank: data,
rankList: data,
isMore: false,
});
}
}
});
}
switchMoreRank = () => {
const { rankList, isMore } = this.state;
if(isMore) {
this.setState({
rank: rankList,
isMore: false,
})
}else {
this.setState({
rank: rankList.filter((item, index) => index < 5),
isMore: true,
})
}
}
render() {
const { rank, isMore } = this.state;
return (
<div data-skip="rank">
<div className="rank-title">
<i className="rank-title__decorate"></i>
<h2 className="rank-title__txt">宝箱达人榜</h2>
<i className="rank-title__decorate"></i>
</div>
<p className="rank-desc">宝箱数量前50名可额外获得一份奖品,数量相同的用时短者排名在前</p>
<dl className="rank-header">
<dd className="rank-column">排名</dd>
<dd className="rank-column">用户</dd>
<dd className="rank-column">宝箱数量</dd>
<dd className="rank-column">奖品</dd>
</dl>
<div className="rank-body">
{
rank.map((item, index) => (
<dl className="rank-item" key={index}>
<dd className="rank-column">
{
index <= 2
? <span className="rank-column__number" data-num={index}></span>
: <span>{index+1}</span>
}
</dd>
<dd className="rank-column">
<span className="rank-column__name">{item.user_name}</span>
</dd>
<dd className="rank-column">
<span>{item.num}</span>
</dd>
<dd className="rank-column">
{
item.url
? <a className="rank-column__txt" href={item.url}>{item.prize_name}</a>
: <span className="rank-column__txt">{item.prize_name}</span>
}
</dd>
</dl>
))
}
<div className="rank-more" onClick={this.switchMoreRank}>
<span className="rank-more__txt">{isMore? '展开' : '收起'}</span>
<i className="rank-more__icon" data-more={isMore}></i>
</div>
</div>
</div>
)
}
}
export default TreasureRank;
\ No newline at end of file
[data-skip="rank"] {
.rank-title {
display: flex;
align-items: center;
justify-content: center;
}
.rank-title__decorate {
display: inline-block;
width: 11px;
height: 12px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-decorate-0.png');
}
.rank-title__txt {
position: relative;
margin: 0 8px;
font-size: 18px;
font-weight: normal;
color: #FFE300;
text-align: center;
line-height: 1;
&::after {
content: '';
position: absolute;
top: -8px;
right: -8px;
width: 14px;
height: 11px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-decorate-1.png');
}
}
.rank-desc {
margin: 7px 0 0;
padding: 0 48px;
font-size: 12px;
color: #FFE300;
text-align: center;
line-height: 16px;
}
.rank-header {
margin: 12px 10px 0;
border-radius: 5px 5px 0 0;
font-size: 0;
overflow: hidden;
.rank-column {
color: #1D5432;
font-size: 12px;
line-height: 30px;
background-color: #FFE300;
}
}
.rank-body {
margin: 0 10px;
border-left: 1px solid #81F3AF;
border-bottom: 1px solid #81F3AF;
border-right: 1px solid #81F3AF;
border-radius: 0 0 5px 5px;
background-color: #1D5432;
}
.rank-item {
border-bottom: 1px solid #0E7442;
.rank-column {
display: inline-flex;
align-items: center;
justify-content: center;
height: 40px;
font-size: 12px;
color: #fff;
}
}
.rank-column {
display: inline-block;
text-align: center;
vertical-align: middle;
&:nth-child(1) {
width: 10%;
}
&:nth-child(2) {
width: 25%;
}
&:nth-child(3) {
width: 20%;
}
&:nth-child(4) {
width: 45%;
}
}
.rank-column__number {
display: inline-block;
width: 11px;
height: 12px;
background-size: cover;
&[data-num="0"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/-s-diyiming.png');
}
&[data-num="1"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/-s-dierming.png');
}
&[data-num="2"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/-s-disanming.png');
}
}
.rank-column__name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.rank-column__txt {
display: inline-block;
width: 100%;
box-sizing: border-box;
padding: 0 5px;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
a.rank-column__txt {
text-decoration: underline;
}
.rank-more {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
}
.rank-more__txt {
font-size: 14px;
color: #fff;
}
.rank-more__icon {
width: 11px;
height: 12px;
margin-left: 5px;
background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/icon-arrow-double.png');
&[data-more="false"] {
transform: rotate(180deg);
}
}
}
import React, { Component } from 'react';
import './team.scss'
import { getParam, http, SendMessageToApp } from "@/utils"
import { Toast } from 'antd-mobile';
import {withRouter} from 'react-router-dom';
import {compose} from "redux"
import { connect } from "react-redux";
class TeamInfo extends Component {
constructor(props) {
super(props);
this.state = {
is_my_team: false, // 是否有自己的队伍
prize_info: [],
info: {
removable: 0,
total: 0
},
member: [],
removable_data: [],
my_team: {},
}
}
componentDidMount() {
this.getTeamInfo();
}
// 获取队伍信息
getTeamInfo = () => {
http.get(`${API.home}/sys/treasure/teamInfo`).then(res => {
const { code, data, msg } = res.data;
if (code === 200) {
const { prize_info, is_my_team, info, member, removable_data, my_team } = data;
this.setState({
prize_info,
is_my_team,
info,
member: this.fillTeam(member),
removable_data,
my_team
})
let currentId = null;
if(info.removable > 0) {
currentId = removable_data[0].id;
}
this.props.getRemovable(info.removable, currentId);
} else {
Toast.info(msg);
}
})
}
// 跳转到我的宝箱页
toYearTreasure = (close) => {
if(this.props.user.hasError) {
this.toLogin();
} else {
let search = '';
if(close) {
const {removable_data, info: {removable}} = this.state;
if(removable > 0) {
let current = removable_data[0];
search = `?id=${current.id}`;
}
}
this.props.history.push(`/year/yearTreasure${search}`);
}
}
// 去登录
toLogin = () => {
if (!getParam('version')) {
this.props.history.push('/passport/login')
} else {
SendMessageToApp("toLogin")
}
}
// 邀请好友组队
createTeam = () => {
if(this.props.user.hasError) {
this.toLogin();
} else {
const {is_my_team, my_team: {treasure_code}} = this.state;
if(is_my_team) { // 有自己的队伍
// 直接跳转
this.props.history.push('/activity/newyear-2019/landing?origin=1&treasure_code=' + treasure_code);
}else{ // 没自己的队伍
// 请求创建队伍的接口
http.get(`${API.home}/sys/treasure/createMyTeam`).then(res => {
const { code, data, msg } = res.data;
if (code === 200) {
const { treasure_code } = data;
this.props.history.push('/activity/newyear-2019/landing?origin=1&treasure_code=' + treasure_code);
} else {
Toast.info(msg);
}
});
}
}
}
// 队伍成员信息必须满五个 不满的需要填充
fillTeam = (list) => {
let len = list.length;
for(let i=0;i<5-len;i++) {
list.push({
head_img: '',
user_name: '',
nobody: true,
})
}
return list;
}
render() {
const { prize_info, is_my_team, info: {removable, total}, member } = this.state;
let name = '', stage_no = 0;
if(prize_info.length > 0) {
name = prize_info[0].name;
stage_no = prize_info[0].stage_no;
}
// 显示文案控制
let Text = '';
if(total === 0) {
Text = `我的宝箱`;
} else if (removable === 0) {
Text = `共${total}个宝箱`;
} else {
Text = `共${total}个宝箱/${removable}个未开`;
}
return (
<div className='team_info__container'>
<div className='team__member'>
<ul className='member__list'>
{
member && member.length > 0 && (
member.map((item, index) => {
return <li key={index} className='member__item'>
<div className='avatar__container'>
{
item.nobody ? (
<img className='head__image' src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/default-member-avatar.png" alt=""/>
) : (
<img className='head__image' src={item.head_img} alt=""/>
)
}
{
index === 0 ? (
<img className='caption__flag' src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/caption.png" alt=""/>
) : (null)
}
<div className='shadow'></div>
</div>
<div className={`member__join ${item.nobody ? '' : 'join'}`}></div>
</li>
})
)
}
</ul>
<div className='box__number'>
<img onClick={() => this.toYearTreasure(true)} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/treasure-box-icon.png" alt="" />
<p onClick={() => this.toYearTreasure(false)} className='box__text'>
{Text}
</p>
<img className='position__arrow' src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/arrow_jinzhan.png" alt=""/>
{
removable > 0 && (
<div className='position__number'>{removable}</div>
)
}
</div>
</div>
<div onClick={this.createTeam} className='invite__btn'>
{
is_my_team ? ('继续组队') : ('组队开宝箱')
}
</div>
{
stage_no > 0 && name && <p className='stage_prize'>{`第${stage_no}次必中${name}`}</p>
}
</div>
)
}
}
export default compose(
connect(
state => ({user: state.user}),
null
),
withRouter
)(TeamInfo)
.team_info__container {
margin-bottom: 30px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
.team__member {
height: 72px;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 16px;
.member__list {
height: 50px;
width: 224px;
display: flex;
justify-content: flex-start;
align-items: center;
margin-right: 12px;
.member__item {
width: 44px;
height: 50px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
margin-left: 1px;
&:first-child {
margin-left: 0;
.member__join {
border-radius: 2px 0 0 2px;
}
}
&:last-child {
.member__join {
border-radius: 0 2px 2px 0;
}
}
.avatar__container {
width: 27px;
height: 27px;
position: relative;
border: 1px solid #fff;
border-radius: 50%;
.head__image {
border-radius: 50%;
width: 100%;
height: 100%;
}
.shadow {
width: 24px;
height: 3px;
background: #1a3528;
border-radius: 50%;
position: absolute;
bottom: -6px;
}
.caption__flag {
position: absolute;
width: 18px;
height: 10px;
left: 50%;
top: 0;
}
}
.member__join {
width: 40px;
height: 5px;
background: rgba(0, 88, 51, 1);
box-shadow: 1px 1px 2px 0px rgba(3, 52, 91, 0.35);
}
.join {
background: rgba(255, 221, 29, 1);
box-shadow: 1px 2px 2px 0px rgba(253, 253, 253, 0.46) inset,
1px 2px 2px 0px rgba(253, 253, 253, 0.46) inset;
}
}
}
.box__number {
width: 108px;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
position: relative;
img {
width: 92px;
height: 50px;
}
.box__text {
width: 1000px;
font-size: 100px;
transform: scale(0.1);
text-decoration: underline;
color: rgba(255, 227, 0, 1);
position: absolute;
bottom: -72px;
text-align: center;
}
.position__arrow {
width: 18px;
height: 18px;
position: absolute;
left: -7px;
top: 18px;
}
.position__number {
min-width: 22px;
height: 18px;
font-size: 12px;
background: rgba(255, 60, 22, 1);
border: 1px solid rgba(255, 227, 0, 1);
border-radius: 9px 9px 9px 0px;
color: rgba(255, 227, 0, 1);
position: absolute;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
right: -4px;
top: -4px;
}
}
}
.invite__btn {
width: 320px;
height: 44px;
background: rgba(255, 227, 0, 1);
border-radius: 3px;
display: flex;
justify-content: center;
align-items: center;
font-size: 15px;
color: rgba(11, 123, 69, 1);
margin-bottom: 12px;
}
.stage_prize {
font-size: 12px;
line-height: 12px;
color: rgba(255, 227, 0, 1);
text-align: center;
}
}
import React, {Component} from 'react'
import './index.scss'
import {http, SendMessageToApp, getParam} from '@/utils'
import CommonContainer from './../common/commonContainer/index'
import CourseItem from '../../../blessingPreheat/courseItem/index'
import {withRouter} from "react-router-dom"
class YarnWish extends Component {
state = {
list: [],
activityStage: 1,
}
componentDidMount() {
this.fetchCourse()
this.getStage()
}
componentWillUpdate() {
const {activityStage} = this.state
if (activityStage == 1) {
document.title = `七月在线年终大回馈,人气好课免费学,精品课程1分抢!`
} else {
document.title = `七月在线年终大回馈,人气好课免费学,精品课程1分抢!`
}
}
fetchCourse = () => {
http.get(`${API.home}/activity/wish_course`).then(res => {
const {code, data} = res.data
if (code === 200) {
this.setState({
list: JSON.stringify(data) === '{}' ? [] : data
})
} else if (code === 4030) {
this.props.history.push('/passport/login')
}
})
}
getStage = () => {
http.get(`${API.home}/activity/stage`).then(res => {
const {code, data} = res.data
if (code === 200) {
this.setState({
activityStage: data.activity_stage // 0-不在活动时间 1-预热 2-正式 3-返场
})
}
})
}
// 去课程详情页
toCourse = (courseId) => {
const {history} = this.props
if (!getParam('version')) {
history.push(`/detail?id=${courseId}`)
} else {
SendMessageToApp("toCourse", courseId)
}
}
render() {
const {list, activityStage} = this.state
return (
<div className='year-wish'>
<div className="banner"><img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/xy_banner_bj.png" alt=""/></div>
{
list.length > 0 ? <CommonContainer>
<div className='groupcourse course-box'>
{
list && list.length > 0 && list.map(item => (
<CourseItem image={item.image_name} key={item.course_id} id={item.course_id}
toCourse={this.toCourse}>
{
item.type == 4 && item.is_buy != 1 &&
<div className="group-num">限量300</div>
}
<div className="coupon-course__footer">
{
item.is_buy == 1 &&
<>
<p className={'course-title text-overflow-1'}>{item.course_title}</p>
<a onClick={() => this.toCourse(item.course_id)}
className="btn to-study">开始学习</a>
</>
}
{
item.is_buy == 0 &&
<>
<div className="type">
{
item.type == 0 &&
<>
<span className="tag">活动价</span>
<span className="time">12.23开始</span>
</>
}
{
(item.type == 1 || item.type == 4) &&
<>
<span className="tag">拼团价</span>
<span className="time">12.23开团</span>
</>
}
{
item.type == 2 &&
<>
<span className="tag">好友帮帮砍</span>
<span className="time">12.23开砍</span>
</>
}
</div>
<div className="price">
{item.type == 2 ? '到手最低:¥' : '¥'}
<span
className="new-price">{item.type == 4 ? '0.01' : item.price2}</span>
<span className="old-price"> 现价:<s>¥{item.price1}</s></span>
</div>
<div className="status">
<a onClick={() => this.toCourse(item.course_id)}
className="status-btn to-buy">直接购买</a>
{
item.is_join == 1 &&
<a className="status-btn add-wish"><img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/add-success.png"
alt=""/>已加心愿单</a>
}
{
item.is_join == 0 &&
<a
onClick={() => this.addWishList(item.course_id)}
className="status-btn add-wish-success">
<img
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/like_icon.png"
alt=""/>加入心愿单
</a>
}
</div>
</>
}
</div>
</CourseItem>
))
}
</div>
</CommonContainer>
: <div className="notData">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-empty.png" alt=""/>
{
activityStage == 1 ? <p>你的心愿单目前空空如也,<br/>快去挑选更多优惠课程吧~</p>
: <p>你的心愿单没有课程哦,<br/>感兴趣的课程可在双旦主会场直接购买!</p>
}
</div>
}
</div>
)
}
}
export default withRouter(YarnWish)
html, body, #root {
height: 100%;
}
.year-wish {
min-height: 100%;
background-color: #BA2C21;
padding-bottom: 35px;
.banner {
width: 100%;
margin-bottom: 30px;
}
.course-box {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.course-container {
width: 158px;
margin: 15px 0 0 0;
text-align: center;
position: relative;
}
.group-num {
width: 66px;
height: 16px;
position: absolute;
left: 10px;
top: 10px;
line-height: 16px;
background: #CA161C;
opacity: 0.8;
border-radius: 1px;
font-size: 12px;
color: #fff;
text-align: center;
}
.coupon-course__footer {
.course-title {
padding-left: 10px;
font-size: 15px;
color: #333;
font-weight: 500;
margin-top: 7px;
}
.btn {
display: inline-block;
width: 138px;
height: 24px;
text-align: center;
line-height: 24px;
border-radius: 2px;
font-size: 12px;
outline: none;
border: none;
letter-spacing: 1px;
}
.big-course {
background-color: #FEE41D;
border: 1px solid #090F08;
color: #090F08;
margin-top: 10px;
}
.to-study {
background-color: #09f;
color: #fff;
position: absolute;
left: 10px;
bottom: 10px;
}
.free-study {
background: linear-gradient(-90deg, #EB1612 0%, #F92927 100%);
color: #fff;
margin-top: 10px;
}
.free-course-num {
font-size: 12px;
color: #070F08;
margin-top: 7px;
letter-spacing: 1px;
span {
font-size: 14px;
color: #FF0002;
}
}
}
.type {
text-align: left;
padding-left: 7px;
margin-top: 3px;
.tag {
display: inline-block;
padding: 0 6px;
height: 14px;
line-height: 15px;
text-align: center;
font-size: 12px;
color: #FFF;
position: relative;
z-index: 0;
}
.time {
display: inline-block;
height: 15px;
line-height: 15px;
padding: 0 6px;
margin-left: 5px;
position: relative;
font-size: 12px;
color: #555;
text-align: center;
z-index: 0;
}
.time:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #E6E6E6;
transform: skewX(-20deg);
z-index: -1;
}
.tag:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #FF0002;
transform: skewX(-20deg);
z-index: -1;
}
}
.price {
text-align: left;
padding-left: 5px;
margin-top: 3px;
color: #FF0002;
font-size: 12px;
.new-price {
font-size: 18px;
}
.old-price {
font-size: 12px;
color: #666;
margin-left: 8px;
}
}
.status {
text-align: left;
padding-left: 5px;
position: absolute;
bottom: 10px;
.status-btn {
display: inline-block;
height: 22px;
line-height: 22px;
border-radius: 2px;
text-align: center;
font-size: 12px;
color: #fff;
}
.to-buy {
width: 148px;
background-color: #FF8080;
}
}
}
.groupcourse .course-container {
height: 195px;
}
.notData {
margin: 100px auto 0;
text-align: center;
img {
width: 56px;
height: 49px;
}
p{
font-size: 16px;
color: #fff;
margin-top: 20px;
}
}
}
.year-wish + .year19-index {
display: none;
}
......@@ -284,6 +284,7 @@ class BargainMiddlePage extends Component {
}
this.getBargainInfo()
this.getBargainRankList(getParam('id'), 1)
} else if (res.data.code == 4030 || res.data.code == 4040) {
......@@ -376,6 +377,9 @@ class BargainMiddlePage extends Component {
if(bargain_status === 0) {
bargainBtn = <button className='active-btn' onClick={this.shareFriendBargain}>邀请好友砍价</button>
}
else {
bargainBtn = <button className={'invalid-btn'}>砍价结束</button>
}
}else {
if(assist_status === 0 && bargain_status === 0) {
bargainBtn = <button className='active-btn' onClick={this.friendBargainFirst}>帮好友砍一刀</button>
......@@ -422,6 +426,9 @@ class BargainMiddlePage extends Component {
/>
</ul>
<div className="bargain-detail">
{
(this.state.data.bargain_status == 0 || this.state.data.bargain_status == 1) &&
<div>
<div className="top">
<div>
已砍<span className={'reduced-price'}>{this.state.bargainData.bargain_price}</span>
......@@ -446,6 +453,8 @@ class BargainMiddlePage extends Component {
<div className="middle">
<span style={{width: this.state.width}}></span>
</div>
</div>
}
{
this.state.isOriginator === 1 && this.state.data.bargain_status === 0 &&
<div>
......@@ -625,13 +634,13 @@ function CourseDes(props) {
<span className={'discount-price'}>{course.course_price}</span>
{/* is_originator 是否发起人 0-否 1-是 */}
{
(is_originator === 1 && bargain_status !== 3) &&
(is_originator == 1 && bargain_status != 3) &&
<button className={'purchase-btn'} onClick={toCart}>
¥{course.pay_price}去支付
</button>
}
{
(is_originator === 1 && bargain_status === 3) &&
(is_originator == 1 && bargain_status == 3) &&
<span className="course-button__buy--done">已购买</span>
}
</div>
......
......@@ -135,8 +135,9 @@ class BlessingGetPrize extends Component {
{
(!prize_data || prize_data.length === 0) && (
<div className="active_over_container">
<img src='https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/acitve__over.png' alt=''/>
<p>七月在线双十一抽奖活动已结束, 感谢你的参与!</p>
<p>AI充电节返场已开启</p>
<p>狂欢不能停~</p>
<a href='/blessingPreheat' className='to_active'>立即查看</a>
</div>
)
}
......
......@@ -199,22 +199,30 @@
.active_over_container {
display: flex;
flex-direction: column;
justify-content: flex-start;
justify-content: center;
align-items: center;
margin-top: 70px;
img {
width: 170px;
height: 134px;
}
width: 340px;
height: 156px;
margin: 4px auto;
background: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/active_over.png') center center no-repeat;
background-size: 100% 100%;
p {
width:238px;
height:39px;
font-size:16px;
font-weight:400;
font-size:18px;
font-weight:500;
color:rgba(76,33,239,1);
line-height:27px;
}
.to_active {
width:298px;
height:44px;
background:linear-gradient(90deg,rgba(255,105,5,1) 0%,rgba(255,180,5,1) 100%);
border-radius:5px;
font-size:18px;
font-weight:500;
color:rgba(255,255,255,1);
line-height:24px;
text-align: center;
text-align-last: center;
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
}
}
......
......@@ -97,10 +97,10 @@ class Banner extends Component {
render() {
const { toSection, navs, index, isFormal } = this.props;
const { toSection, navs, index, isFormal, onlyShow } = this.props;
return (
<div id={'main-banner'}>
<div className={`banner ${isFormal ? 'formal_banner' : ''}`}></div>
<div className={`banner ${isFormal ? 'formal_banner' : ''} ${onlyShow ? 'fc_banner' : ''}`}></div>
<nav id={'main-nav'}>
<ul>
{
......
#main-banner{
overflow: auto;
margin-bottom: 70px;
.banner{
width: 375px;
height: 183px;
......@@ -11,6 +10,10 @@
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/formal_banner.png") no-repeat;
background-size: contain;
}
.fc_banner {
background: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/fc_banner.png') center center no-repeat;
background-size: 100% 100%;
}
#main-nav{
position: absolute;
top: 183px;
......
......@@ -46,9 +46,9 @@ class FormalDraw extends Component {
.then(res => {
const {data, code, msg} = res.data
if (code == 200) {
const {today} = data.value
const oneDay = data.list.filter(item => item.date === data.value.today)
const activeIndex = oneDay[0]['son'].findIndex(item => item.status == 3)
let oneDay = data.list.find(item => item.date === data.value.today) || data.list[0]
const today = oneDay.date
const activeIndex = oneDay['son'].findIndex(item => item.status == 3)
this.setState({
tabs: data.list.map(item => ({title: item.date})),
today,
......
......@@ -111,6 +111,10 @@ class BlessingPreheat extends Component {
id: 'best-courses'
},
{
text: '大咖直播',
id: 'live'
},
{
text: '幸运大抽奖',
id: 'lucky-draw'
},
......@@ -122,10 +126,6 @@ class BlessingPreheat extends Component {
text: 'AI测试',
id: 'ai-test'
},
{
text: '大咖直播',
id: 'live'
},
],
index: 0,
userHasError: props.user.hasError,
......@@ -142,9 +142,13 @@ class BlessingPreheat extends Component {
}
componentDidMount() {
const _this = this;
this.fetchUserBlessing()
this.setInitialNavActiveStatus()
window.addEventListener('scroll', throttle(this.calcNavActive, 100))
// 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万元奖品来就送!!',
......@@ -178,9 +182,12 @@ class BlessingPreheat extends Component {
}
componentWillUpdate() {
const {isFormal} = this.state;
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折秒课,海量奖品来就送-七月在线`
}
......@@ -260,6 +267,9 @@ class BlessingPreheat extends Component {
return findIndex(navs, item => item.id === str)
}
componentWillUnmount () {
window.removeEventListener('scroll', this.calcNavActive);
}
setInitialNavActiveStatus = () => {
const observer = new MutationObserver(debounce((list, observer) => {
......@@ -282,12 +292,21 @@ class BlessingPreheat extends Component {
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))
})
}
}
}
......@@ -303,9 +322,13 @@ class BlessingPreheat extends Component {
const {code, data} = res.data
if (code === 200) {
if(data.is_over) {
if(!getParam('version')) {
history.push('/');
} else {
SendMessageToApp("toQualityCourse");
}
this.setState({
}
this.setState(()=>({
isSign: !!data.today_signed,
isFormal: data.is_activity,
onlyShow: data.onlyShow,
......@@ -316,7 +339,7 @@ class BlessingPreheat extends Component {
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()
}
......@@ -445,14 +468,23 @@ class BlessingPreheat extends Component {
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')
......@@ -610,9 +642,10 @@ class BlessingPreheat extends Component {
navs={navs}
toSection={this.toSection}
index={index}
onlyShow={onlyShow}
/>
{/* 精品课程特惠专区 */}
{/* 精品课程特惠专区--返场 */}
{
onlyShow && (
<>
......@@ -628,11 +661,21 @@ class BlessingPreheat extends Component {
)
}
{/* 大咖直播--返场 */}
{
onlyShow && <Live isFormal={isFormal} isLogin={isLogin}/>
}
{/* 抽奖--正式 */}
{
isFormal === 1 &&
<>
<ListHeader id={'lucky-draw'} text="幸运大抽奖" styles={{margin: '30px 0 10px'}}/>
<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>
......@@ -644,6 +687,11 @@ class BlessingPreheat extends Component {
{/* 积福气 */}
<ListHeader id={'lucky-value'} text="积福气,享受更多福利" styles={{margin: '30px 0 15px'}}/>
{
onlyShow ? (
<p className='active_over'>活动已结束</p>
) : null
}
<Link className="blessing__sort" to="/blessingRank"></Link>
......@@ -717,7 +765,11 @@ class BlessingPreheat extends Component {
<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>
......@@ -731,7 +783,11 @@ class BlessingPreheat extends Component {
<RankList></RankList>
<Live isFormal={isFormal} isLogin={isLogin}/>
{/* 大咖直播 -- 正式活动 */}
{
!onlyShow && <Live isFormal={isFormal} isLogin={isLogin}/>
}
{
addressPopupVisible &&
<div className="address-mask">
......@@ -749,7 +805,7 @@ class BlessingPreheat extends Component {
/>
<input type="tel"
placeholder={'联系方式'}
name={'tel'}
name={'phone'}
onChange={e => {
this.setAddressState(e)
}}
......
#blessing-preheat {
background: #5327FA;
padding-bottom: 30px;
.active_over {
font-size: 20px;
color: #fff604;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10px;
}
}
.test__record {
......
......@@ -79,7 +79,7 @@ class UseCoupon extends PureComponent {
}
}
if (state.from === '/order') {
const coupon = data.data
/*const coupon = data.data
if (coupon['ctype'] == 2
&& coupon['limit_course'] != this.state.courseId) {
......@@ -93,7 +93,7 @@ class UseCoupon extends PureComponent {
valid_coupons: [...this.state.valid_coupons, coupon],
redeemCode: ''
})
}
}*/
Toast.info('兑换成功')
this.getAllCoupons()
}
......@@ -143,7 +143,7 @@ class UseCoupon extends PureComponent {
const [expansionCoupons, selectCoupons] = coupons
const {data: select} = selectCoupons
const {data: expansion} = expansionCoupons
let PzCoupon = this.state.valid_coupons.concat(expansion.data)
let PzCoupon = Array.isArray(expansion.data) ? expansion.data : []
if (expansion.code == 200) {
Array.isArray(expansion.data)
&& (expansion.data = expansion.data.map(item => (item.ctype = 4, item)))
......
......@@ -65,19 +65,16 @@ class ToGroup extends Component {
if (res.data.data.is_success === 0) {
let date = res.data.data.end_time * 1000,
day = 0,
hours = 0,
minutes = 0,
seconds = 0;
setInterval(() => {
date -= 1000
day = `${parseInt(date / (3600000 * 24))}`.padStart(2, 0);
hours = `${parseInt((date- day * 3600000 * 24)/3600000)}`.padStart(2, 0);
minutes = `${parseInt((date - day * 3600000 * 24 - hours * 3600000) / 60000)}`.padStart(2, 0);
seconds = `${parseInt((date - day * 3600000 * 24 - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
hours = `${parseInt(date / (60 * 60 * 1000))}`.padStart(2, 0);
minutes = `${parseInt((date - hours * 3600000) / 60000)}`.padStart(2, 0);
seconds = `${parseInt((date - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
this.setState({
// countdown: `${day}:${hours}:${minutes}:${seconds}`
countdown: `${day}${hours}${minutes}分`
countdown: `${hours}:${minutes}:${seconds}`
});
}, 1000)
}
......
......@@ -345,19 +345,16 @@ class Detail extends Component {
if (course_info.group_status === 3 || course_info.group_status === 4) {
let endTime = course_info.pdd_group_info.groupon_member.end_time;
let date = endTime * 1000,
day = 0,
hours = 0,
minutes = 0,
seconds = 0;
setInterval(() => {
date -= 1000
day = `${parseInt(date / (3600000 * 24))}`.padStart(2, 0);
hours = `${parseInt((date- day * 3600000 * 24)/3600000)}`.padStart(2, 0);
minutes = `${parseInt((date - day * 3600000 * 24 - hours * 3600000) / 60000)}`.padStart(2, 0);
seconds = `${parseInt((date - day * 3600000 * 24 - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
hours = `${parseInt(date / (60 * 60 * 1000))}`.padStart(2, 0);
minutes = `${parseInt((date - hours * 3600000) / 60000)}`.padStart(2, 0);
seconds = `${parseInt((date - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
this.setState({
// countdown: `${day}:${hours}:${minutes}:${seconds}`
countdown: `${day}${hours}${minutes}分`
countdown: `${hours}:${minutes}:${seconds}`
});
}, 1000)
}
......@@ -704,15 +701,15 @@ class Detail extends Component {
*/
}
{/*双十一期间不需要显示 不要删除*/}
{/*{*/}
{/*isCent && !course_info.is_aist && (course_info.group_status === 3 || course_info.group_status === 4) &&*/}
{/*<Group*/}
{/*courseInfo={course_info}*/}
{/*history={this.props.history}*/}
{/*countdown={countdown}*/}
{/*invitedFriends={this.invitedFriends}*/}
{/*/>*/}
{/*}*/}
{
isCent && !course_info.is_aist && (course_info.group_status === 3 || course_info.group_status === 4) &&
<Group
courseInfo={course_info}
history={this.props.history}
countdown={countdown}
invitedFriends={this.invitedFriends}
/>
}
{/*
* 砍价
......
......@@ -127,6 +127,11 @@ class MyOrders extends Component {
id={item.course_id}
toDetail={this.toCourseDetail}
/>
{
item.course_expire && item.course_expire!='' &&
<span className='course-expire'>{item.course_expire}</span>
}
</div>
)
})
......@@ -135,12 +140,18 @@ class MyOrders extends Component {
<PayInfo item={item} cancel={this.cancel}/>
{
item.type == 5 && item.is_buy == 0 &&
item.type == 5 && item.is_buy == 0 && item.is_overdue == 0 &&
<div className={'expand-pay-wk'}>
<span className={'expand-pay-time'}>{item.final_end_time}结束付尾款</span>
<span>还需支付尾款</span>
</div>
}
{
item.type == 5 && item.is_buy == 0 && item.is_overdue == 1 &&
<div className={'expand-pay-wk'}>
<span>支付尾款时间已过</span>
</div>
}
</div>
)
})
......
......@@ -37,6 +37,21 @@
padding: 10px 12px;
background-color: $bg_fff;
border-bottom: 1px solid $border_e7eaf1;
position: relative;
.course-expire{
display: block;
width:92px;
height:20px;
line-height: 20px;
background:#FF3A3A;
border-radius:0 10px 10px 0;
position: absolute;
color: #FFF;
font-size: 12px;
left: 12px;
bottom: 20px;
text-align: center;
}
}
.order-info {
......
......@@ -33,8 +33,8 @@ const ShareCourse = loadable(() => import(/* webpackChunkName: 'ShareCourse'*/'@
const Country = loadable(() => import(/* webpackChunkName: 'Country' */'@/components/country/index'))
const ExpandCallback = loadable(() => import('@/components/expand/callback'))
const ExpandShare = loadable(() => import('@/components/expand/share'))
const Activity = loadable(() => import(/* webpackChunkName: 'Activity' */'@/components/activity/index'))
const Invite = loadable(() => import(/* webpackChunkName: 'Invite' */'@/components/activity/invite'))
const Activity = loadable(() => import(/* webpackChunkName: 'Activity' */'@/components/activity/1111/index'))
const Invite = loadable(() => import(/* webpackChunkName: 'Invite' */'@/components/activity/1111/invite'))
export default [
{
path: '/',
......@@ -187,7 +187,7 @@ export default [
},
{
path: '/prize-winner-list',
component: loadable(() => import(/* webpackChunkName: 'prize-winner-list' */'@/components/activity/prize-winner-list'))
component: loadable(() => import(/* webpackChunkName: 'prize-winner-list' */'@/components/activity/1111/prize-winner-list'))
},
//定金订单页面
{
......@@ -220,10 +220,35 @@ export default [
},
{
path: '/activity',
exact: true,
component: Activity,
},
{
path: '/invite',
component: Invite,
},
//双旦活动
{
path: '/activity/newyear-2019/landing',
component: loadable(() => import(/* webpackChunkName: 'newyear-2019-landing'*/ '@components/activity/newyear-2019/landing/index'))
},
// 双旦活动预热页面
{
path: '/year/yearIndex',
component: loadable(() => import(/* webpackChunkName: 'newyear-yearIndex' */ '@components/activity/newyear-2019/preheat/index'))
},
// 我的宝箱
{
path: '/year/yearTreasure',
component: loadable(() => import(/* webpackChunkName: 'newyear-yearIndex' */ '@components/activity/newyear-2019/myTreasure/index'))
}
,
// 双旦心愿单
{
path: '/year/yearWish',
component: loadable(() => import(/* webpackChunkName: 'newyear-yearIndex' */ '@components/activity/newyear-2019/year-wish/index'))
}
]
......@@ -15,8 +15,10 @@ const accountLogin = user => dispatch => {
}
const quickLogin = user => dispatch => {
return http.post(`${API['passport-api']}/quick_login`, user)
.then(res => {
return http.post(`${API['passport-api']}/quick_login`, {
...user,
plat: 5
}).then(res => {
return storeUser(res, dispatch)
})
}
......
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