Commit 98d6cad9 by zhanghaozhe

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

 Conflicts:
	src/common/closable-popup/index.js
parents 43bdf9ef 844f037b
.captcha-container { .captcha-container {
position: relative; position: relative;
width: 100%; width: 100%;
height: 40px; // height: 40px;
} }
.captcha-animation { .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 { handleToHide } = this.props;
http.post(`${API.home}/sys/collect_info`, params).then(res => {
const {code, msg} = res.data;
if (code === 200) {
handleToHide();
} 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}>
{
prize ? (
<p className='address__prize'>您抽中了{prize}<span style={{'color': '#FF4000'}}>实物奖品</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__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 {
constructor(props) {
super(props),
this.state = {
validate: '',
captchaInstance: null,
seconds: 60,
isFirst: true,
timer: null,
isTimer: false, // 是否开始倒计时
accountInfo: {},
bindInfo: {},
country: {
num: '86'
}
}
}
getCaptchaInstance = instance => {
this.setState({
captchaInstance: instance
});
}
onVerify = (err, data) => {
if (err) {
console.log(err);
} else {
this.setState({
validate: data.validate
});
}
}
handleToSend = ({tel, code}) => {
let { validate, seconds, isFirst, isTimer, captchaInstance, country: {num = '86'} } = this.state;
if(validate) {
if (!isFirst) {
Toast.info('请重新进行滑块验证', 2, null, false);
captchaInstance.refresh();
this.setState({
isFirst: true
});
return
}
if(!isTimer) {
if (!tel) {
Toast.info('手机号码不能为空', 2, null, false);
}else if(!/^\d+$/.test(tel)) {
// }else if (!validateTel(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;
}
// 绑定手机
toContinueBind = (isValid = 1) => {
const { accountInfo: { tel, code}, country: {num = '86'} } = this.state;
// is_valid 是否验证 1:验证(默认),0不验证
http.post(
`${API['passport-api']}/m/personal/bindPhone`,
{
area_code: `00${num}`,
phone_num: tel,
code: code,
type: 1,
is_valid: isValid
}
).then(res => {
const { errno, data, msg } = res.data;
if(errno === 200 ) {
if(isValid) {
if(data.tip_info) {
this.setState({
type: 10,
bindInfo: data.tip_info
})
}else {
this.receviceAfterBind();
}
}else {
this.receviceAfterBind();
}
}else {
Toast.info(msg, 2, null, false);
}
});
}
render() {
const { desc, skip = 'year' } = this.props;
const { country, validate, isTimer } = 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.toContinueBind();
}}
render={({values: {tel, code}, errors}) => (
<Form className="popup-form" data-skip={skip}>
{
desc &&
<div className="poup-form__desc">{desc}</div>
}
<div className="popup-form__item">
<a
className="popup-form__button--num"
to={`/country?id=${getParam('id')}&share_code`}>
+{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__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;
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;
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
.closable-popup-mask { .closable-popup-mask {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
...@@ -8,39 +12,26 @@ ...@@ -8,39 +12,26 @@
z-index: 999; z-index: 999;
.popup-container { .popup-container {
position: absolute;
top: 165px;
left: 50%;
transform: translateX(-50%);
width: 300px;
padding: 20px 10px; padding: 20px 10px;
border-radius: 10px; border-radius: 10px;
background: #fff; background-color: #fff;
.title { .title {
font-size: 16px; font-size: 16px;
color: #525C65; color: #525C65;
text-align: center; text-align: center;
} }
}
.close { .close {
position: absolute; font-size: 36px;
bottom: -74px; color: #fff;
left: 50%; }
transform: translateX(-50%);
font-size: 36px;
color: #fff;
}
.close-icon { .close-icon {
position: absolute; width: 33px;
bottom: -66px; height: 33px;
left: 50%; font-size: 36px;
width: 33px; color: #fff;
height: 33px;
transform: translateX(-50%);
font-size: 36px;
color: #fff;
}
} }
} }
import React, { Component } from 'react';
import './index.scss';
class ConfirmPhone extends Component {
render() {
const { bindInfo = { }, desc, skip = 'year' } = this.props;
return (
<div className="popup-bind" data-skip={skip}>
{
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={() => this.handleToClose(false)}>取消</button>
<button
className="popup-bind__button popup-bind__button--confirm"
onClick={() => this.toContinueBind(0)}>继续绑定</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__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;
}
.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
...@@ -6,8 +6,9 @@ export default class CommonContainer extends Component { ...@@ -6,8 +6,9 @@ export default class CommonContainer extends Component {
super(props) super(props)
} }
render() { render() {
const { id } = this.props;
return ( return (
<div className='common_container'> <div className='common_container' id={id}>
<div className='container_top'></div> <div className='container_top'></div>
<div className='container_content'> <div className='container_content'>
{ {
......
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()}>
<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, { Component } from 'react';
import './index.scss';
class SplitSuccess extends Component {
render() {
const { handleToInvite } = this.props;
return (
<div data-skip="split">
<div className="split-success__image">
<img src="" alt=""/>
</div>
<p className="split-success__prize">AI100题纸质书</p>
<a href="" className="split-success__link">
<span>查看/修改收货信息</span>
</a>
<div className="split-success__member">
<div className="member-item">
<span className="member-item__avatar">
<i className="member-item__captain">队长</i>
</span>
<span className="member-item__prize">AI100题纸质书</span>
</div>
<div className="member-item">
<span className="member-item__avatar">
<i className="member-item__captain">队长</i>
</span>
<span className="member-item__prize">AI100题纸质书</span>
</div>
<div className="member-item">
<span className="member-item__avatar">
<i className="member-item__captain">队长</i>
</span>
<span className="member-item__prize">AI100题纸质书</span>
</div>
<div className="member-item">
<span className="member-item__avatar">
<i className="member-item__captain">队长</i>
</span>
<span className="member-item__prize">AI100题纸质书</span>
</div>
</div>
<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__image {
width: 130px;
height: 103px;
margin: 10px auto 0;
border: 2px solid #CDCDCD;
box-sizing: border-box;
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;
}
.split-success__link {
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 0 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;
}
.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 0 0;
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 { HeaderBar, Popup } from '@common';
import AddressPopup from '@common/addressPopup/index';
import BindPhone from '@common/bindPhone/index';
import ConfirmPhone from '@common/confirmPhone/index';
import TreasureTeam from './team';
import { http } from '@/utils';
import './index.scss';
class MyTreasure extends Component {
constructor(props) {
super(props);
this.state = {
isEnd: false,
isEmpty: false,
seconds: 3,
teams: [],
bindInfo: {
email: 'a',
wechat_nickname: 'b',
qq_nickname: 'c',
sina_nickname: 'd',
}, // 绑定手机号冲突信息
};
}
componentDidMount() {
const { isEnd, bindInfo } = this.state;
if(isEnd) {
this.startCountDown();
}
this.fetchMyTreasure();
this.fetchActivityStatus();
// 绑定地址--宝箱
Popup({
title: '绑定手机号',
content: <BindPhone desc={<>
<p className="phone-treasure__desc">恭喜您获得 奖品名称(现金)</p>
<p className="phone-treasure__notice">为了您的账户安全,请于20191231日前绑定手机号,过期将失效</p>
</>} />
});
}
handleToBindPhone = () => {
}
handleToConfirmPhone = () => {
this.confrimInstance = Popup({
title: '绑定确认',
content: <ConfirmPhone bindInfo={bindInfo} />
});
}
handleToBindAddress = () => {
this.addressInstance = Popup({
title: '收货信息',
skip: 'year',
content: <AddressPopup
skip="year"
tip={
<>
<p className="address-treasure__desc">恭喜您获得 奖品名称奖品名称奖品名称</p>
<p className="address-treasure__notice">请及时填写/确认收货信息,活动结束后统一邮寄</p>
</>
}
handleToHide={() => this.addressInstance.close()}
/>
});
}
fetchMyTreasure = () => {
http.get(`${API.home}/sys/treasure/my`).then(res => {
const { code, data } = res.data;
if(code === 200) {
this.rule = data.rule;
if(Array.isArray(data.team) && data.team.length > 0) {
const teams = data.team.map(item => {
return Object.assign({}, item, {
members: item.member
});
});
this.setState({
isEmpty: false,
teams,
});
}else{
this.setState({
isEmpty: true,
});
}
}
});
}
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);
}
render() {
const { isEnd, isEmpty, seconds, teams } = 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">组队开宝箱</button>
</>
}
{
(!isEnd && !isEmpty) &&
<div className="treasure-content">
{
teams.map((item, index) => (
<TreasureTeam
data={item}
key={index}
handleToBindPhone={this.handleToBindPhone}
handleToBindAddress={this.handleToBindAddress}
/>
))
}
</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;
}
}
// 地址弹窗--宝箱
.address-treasure__desc {
margin: 10px 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 15px 0;
font-size: 14px;
color: #666;
line-height: 1;
}
.phone-treasure__notice {
width: 269px;
margin: 9px 15px 15px;
font-size: 12px;
color: #FF2121;
line-height: 18px;
}
\ No newline at end of file
import React, { Component } from 'react';
import classnames from 'classnames';
import { withRouter, Link } from 'react-router-dom';
import { http } from '@/utils';
import { Popup } from '@common';
import SplitSuccess from './../common/splitSuccess/index';
import './team.scss';
class TreasureTeam extends Component {
constructor(props) {
super(props);
this.state = {
team: {},
currentMember: {}
};
}
componentDidMount() {
this.initMemberInfo();
}
handleToInvite = () => {
const { history } = this.props;
history.push('/activity/newyear-2019/landing');
if(this.splitInstance) {
this.splitInstance.close();
}
}
initMemberInfo = () => {
const { data } = this.props;
let members = data.members;
let len = members.length - 5;
for(; len < 0; len++) {
members.push({});
}
this.setState({
team: Object.assign({}, data, {
members
}),
currentMember: members[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, members = []} } = this.state;
if(is_open) {
const data = members.filter(item => item.uid === id);
this.setState({
currentMember: data[0]
});
}
}
toSplitTreasure = () => {
const { handleToBindPhone, handleToBindAddress } = this.props;
const { team: {captain_uid, team_num} } = this.state;
http.post(`${API.home}/sys/split_treasure`, {
team_num: team_num,
owner_uid: captain_uid
}).then(res => {
const { code, data } = res.data;
if(code === 200) {
// 拆宝箱弹窗--成功
this.splitInstance = Popup({
title: '恭喜你获得',
skip: 'year',
content: <SplitSuccess handleToInvite={this.handleToInvite} />
});
}else if(code === 12000) {
// 绑定手机号
handleToBindPhone();
}else if(code === 12001) {
// 绑定地址
handleToBindAddress();
}
});
}
render() {
const {
team: {
id,
is_captain,
status,
team_num,
lack_member,
is_open,
members = [],
prize_type,
bing_phone,
bing_address,
},
currentMember: {
prize_name
}
} = this.state;
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">
{
members.map((item, index) => (
<div
className={this.computedClass(item.uid)}
onClick={() => this.toCheckPrize(item.uid)}
key={item.id}
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">继续邀请队友</Link>
: <Link className="team-button" to="/activity/newyear-2019/landing">帮好友完成组队</Link>
}
</>
}
{/* 可拆状态 */}
{
(status === 2 && !is_open) &&
<>
<span className="team-icon" data-direction="left"></span>
<span className="team-button--split" onClick={this.toSplitTreasure}></span>
<span className="team-icon" data-direction="right"></span>
</>
}
{/* 已拆状态 */}
{
(status === 2 && is_open) &&
<>
<p className="team-prize">{prize_name}</p>
{/* 第一:是否需要绑定手机号 */}
{
bing_phone &&
<a className="treamsure-team__result" onClick="$emit('to-bind-phone', data.bing_address)">
<span>绑定手机号</span>
</a>
}
{/* 第二:是否需要填写地址 */}
{
(!bing_phone && bing_address) &&
<a className="treamsure-team__result" onClick="$emit('to-bind-address')">
<span>查看/修改收货信息</span>
</a>
}
{/* 第三:奖品,代金券碎片 */}
{
(!bing_phone && !bing_address && prize_type === 6) &&
<a
href="/my/coupon"
target="_blank"
className="treamsure-team__result"
>
可合成代金券在购课时使用,
<span>去合成</span>
</a>
}
{/* 第三:奖品,指定课程代金券 */}
{
(!bing_phone && !bing_address && prize_type === 3) &&
<a
href="/my/coupon"
target="_blank"
className="treamsure-team__result"
>
已发放至您的账户,
<span>去使用</span>
</a>
}
{/* 第三:奖品,通用课程代金券 */}
{
(!bing_phone && !bing_address && prize_type === 4) &&
<a
href="/my/coupon"
target="_blank"
className="treamsure-team__result"
>
已发放至您的账户,
<span>去使用</span>
</a>
}
{/* 第三:奖品,现金红包 */}
{
(!bing_phone && !bing_address && prize_type === 7) &&
<a
href="/my/coupon"
target="_blank"
className="treamsure-team__result"
>
已存入您的账户,
<span>去提现</span>
</a>
}
{/* 第三:奖品,线上课程 */}
{
(!bing_phone && !bing_address && prize_type === 2) &&
<a
href="/my/coupon"
target="_blank"
className="treamsure-team__result"
>已发放至您的账户</a>
}
</>
}
</div>
</div>
)
}
}
export default withRouter(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;
}
}
\ No newline at end of file
import React, { Component } from 'react'; import React, { Component } from 'react';
import './index.scss'; import './index.scss';
import { Toast } from 'antd-mobile'; import { Toast } from 'antd-mobile';
import { http } from '@/utils'; import {Link, withRouter} from "react-router-dom"
import { getParam, http, SendMessageToApp, browser } from "@/utils"
import CommonContainer from './../../common/commonContainer/index' import CommonContainer from './../../common/commonContainer/index'
import CommonPopup from './../../common/commonPopup/index';
export default class index extends Component { 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) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
list: [] list: [],
showMark: false,
subUrl: '',
} }
} }
componentDidMount() { componentDidMount() {
http.get(`${API.home}/sys/get_live_info`).then(res => { this.getLiveInfo();
}
getLiveInfo = () => {
http.get(`${API.home}/activity/get_live_info`).then(res => {
const { code, data, msg } = res.data; const { code, data, msg } = res.data;
if (code === 200) { if (code === 200) {
this.setState({ this.setState({
...@@ -26,18 +38,26 @@ export default class index extends Component { ...@@ -26,18 +38,26 @@ export default class index extends Component {
} }
// 预约直播 // 预约直播
subscribe = (id) => { subscribe = (id) => {
// TODO 检查是否已登录 // 检查是否已登录
// this.checkLogin(); const {hasError, data = {}} = this.props.user;
http.get(`${API['base-api']}/sys/createLiveQrcode/${id}`).then(res => { if(hasError) {
let { errno, data, msg } = res.data; this.props.history.push('/passport/login');
if (errno === 200) { }else{
// this.livingUrl = data.url; http.get(`${API['base-api']}/sys/createLiveQrcode/${id}`).then(res => {
// this.isSubscribe = true; let { errno, data, msg } = res.data;
// TODO 显示二维码地址 并且传递给二维码的图片/地址 if (errno === 200) {
} else { QRCode.toDataURL(data.url, (err, url) => {
Toast.info(msg); this.setState({
} showMark: true,
}); subUrl: url,
})
})
} else {
Toast.info(msg);
}
});
}
} }
// 已预约 给提示 // 已预约 给提示
tip = () => { tip = () => {
...@@ -45,24 +65,65 @@ export default class index extends Component { ...@@ -45,24 +65,65 @@ export default class index extends Component {
} }
// 去直播间 // 去直播间
toLivingRoom = (id) => { toLivingRoom = (id) => {
// TODO 检查是否已登录 const {hasError, data = {}} = this.props.user;
// this.checkLogin(); if(hasError) {
window.location.href = `${window.location.protocol}//www.julyedu.com/live/m_room/${id}` this.props.history.push('/passport/login');
}else{
window.location.href = `${window.location.protocol}//www.julyedu.com/live/m_room/${id}`
}
} }
// 查看回放 // 查看回放
checkVideo = (url) => { checkVideo = (url) => {
// TODO 检查是否已登录 const {hasError, data = {}} = this.props.user;
// this.checkLogin(); if(hasError) {
// TODO 这里需要课程ID this.props.history.push('/passport/login');
const vCourseId = url.split('/')[0]; }else{
history.push(`/play/video?id=${vCourseId}`) 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)
}
} }
render() { render() {
const { list } = this.state; const { list,showMark,subUrl } = this.state;
return ( return (
<div className='live__container'> <div className='live__container'>
<CommonContainer title='大咖直播'> {
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'> <ul className='live__list'>
{ {
list.length && ( list.length && (
...@@ -84,7 +145,7 @@ export default class index extends Component { ...@@ -84,7 +145,7 @@ export default class index extends Component {
</div> </div>
{ {
item.on_live == 0 && item.is_end == 0 && item.is_subscribe == 0 && ( item.on_live == 0 && item.is_end == 0 && item.is_subscribe == 0 && (
<span onClick={this.subscribe(item.live_id)} className="order__btn">立即预约</span> <span onClick={ ()=>this.subscribe(item.live_id)} className="order__btn">立即预约</span>
) )
} }
{ {
...@@ -94,12 +155,12 @@ export default class index extends Component { ...@@ -94,12 +155,12 @@ export default class index extends Component {
} }
{ {
item.on_live == 1 && item.is_end == 0 && ( item.on_live == 1 && item.is_end == 0 && (
<span onClick={this.toLivingRoom(item.room_url)} className="order__btn living">正在直播</span> <span onClick={()=>this.toLivingRoom(item.room_url)} className="order__btn living">正在直播</span>
) )
} }
{ {
item.is_end == 1 && item.transcribe_url != '' && ( item.is_end == 1 && item.transcribe_url != '' && (
<span onClick={this.checkVideo(item.transcribe_url)} className="order__btn check__video">查看回放</span> <span onClick={() => this.checkVideo(item.transcribe_url)} className="order__btn check__video">查看回放</span>
) )
} }
...@@ -114,3 +175,4 @@ export default class index extends Component { ...@@ -114,3 +175,4 @@ export default class index extends Component {
) )
} }
} }
export default withRouter(LiveRoom)
...@@ -97,4 +97,33 @@ ...@@ -97,4 +97,33 @@
} }
} }
} }
.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 {
width: 133px;
height: 30px;
margin-top: 16px;
background: rgba(83, 39, 250, 1);
border-radius: 15px;
font-size: 14px;
color: #fff;
-webkit-appearance: none;
outline: 0;
border: none;
}
} }
.course-box { .year-index-course {
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 { .course-box {
width: 66px; display: flex;
height: 16px; justify-content: space-between;
position: absolute; flex-wrap: wrap;
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-container {
.course-title { width: 158px;
padding-left: 10px; margin: 15px 0 0 0;
font-size: 15px;
color: #333;
font-weight: 500;
margin-top: 7px;
}
.btn {
display: inline-block;
width: 138px;
height: 24px;
text-align: center; text-align: center;
line-height: 24px; position: relative;
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 { .group-num {
background-color: #09f; width: 66px;
color: #fff; height: 16px;
position: absolute; position: absolute;
left: 10px; left: 10px;
bottom: 10px; top: 10px;
} line-height: 16px;
background: #CA161C;
.free-study { opacity: 0.8;
background: linear-gradient(-90deg, #EB1612 0%, #F92927 100%); border-radius: 1px;
font-size: 12px;
color: #fff; color: #fff;
margin-top: 10px; text-align: center;
} }
.free-course-num { .coupon-course__footer {
font-size: 12px; .course-title {
color: #070F08; padding-left: 10px;
margin-top: 7px; font-size: 15px;
letter-spacing: 1px; color: #333;
font-weight: 500;
margin-top: 7px;
}
span { .btn {
font-size: 14px; display: inline-block;
color: #FF0002; 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 { .type {
text-align: left; text-align: left;
padding-left: 7px; padding-left: 7px;
margin-top: 3px; margin-top: 3px;
.tag { .tag {
display: inline-block; display: inline-block;
padding: 0 6px; padding: 0 6px;
height: 14px; height: 14px;
line-height: 15px; line-height: 15px;
text-align: center; text-align: center;
font-size: 12px; font-size: 12px;
color: #FFF; color: #FFF;
position: relative; position: relative;
z-index: 0; 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;
}
} }
.time { .price {
display: inline-block; text-align: left;
height: 15px; padding-left: 5px;
line-height: 15px; margin-top: 3px;
padding: 0 6px; color: #FF0002;
margin-left: 5px;
position: relative;
font-size: 12px; font-size: 12px;
color: #555;
text-align: center;
z-index: 0;
}
.time:before { .new-price {
content: ''; font-size: 18px;
position: absolute; }
top: 0;
right: 0; .old-price {
bottom: 0; font-size: 12px;
left: 0; color: #666;
background-color: #E6E6E6; margin-left: 8px;
transform: skewX(-20deg); }
z-index: -1;
} }
.tag:before { .status {
content: ''; text-align: left;
padding-left: 5px;
position: absolute; position: absolute;
top: 0; bottom: 10px;
right: 0;
bottom: 0;
left: 0;
background-color: #FF0002;
transform: skewX(-20deg);
z-index: -1;
}
}
.price { .status-btn {
text-align: left; display: inline-block;
padding-left: 5px; height: 22px;
margin-top: 3px; line-height: 22px;
color: #FF0002; border-radius: 2px;
font-size: 12px; text-align: center;
font-size: 12px;
color: #fff;
}
.new-price { .to-buy {
font-size: 18px; width: 55px;
} background-color: #FF8080;
}
.old-price { .add-wish, .add-wish-success {
font-size: 12px; width: 88px;
color: #666; margin-left: 5px;
margin-left: 8px; 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%);
}
} }
} }
.status { .bigcourse .course-container {
text-align: left; height: 156px;
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 { .freecourse .course-container {
width: 55px; height: 177px;
background-color: #FF8080; }
}
.add-wish, .add-wish-success { .groupcourse .course-container {
width: 88px; height: 195px;
margin-left: 5px; }
outline: none;
color: #FF0002;
background-color: #fff;
border: 1px solid #FF0002;
img { .ai-course__subtitle {
width: 12px; width: 73px;
height: 11px; height: 24px;
margin-right: 2px; margin: 15px auto 0;
position: relative; border-radius: 12px;
top: 1px; 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;
}
.add-wish-success { .sub__code_container {
color: #fff; padding: 20px;
background: linear-gradient(90deg, rgba(235, 22, 18, 1) 0%, rgba(249, 41, 39, 1) 100%); }
}
.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;
} }
} }
\ No newline at end of file
.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;
}
import React, { Component } from 'react' import React, {Component} from 'react'
import './index.scss' import './index.scss'
import LiveRoom from './LiveRoom/index'; import LiveRoom from './LiveRoom/index'
import YearCourse from './YearCourse/index'; import YearCourse from './YearCourse/index'
import TreasureBox from './../treasure-box/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 {addDays} from "date-fns"
export default class index extends Component { export default class index extends Component {
render() { state = {
return ( userInfoList: [],
<div className={'year-index'}> userInfo: {},
<LiveRoom /> isAppUpdate: false,
<YearCourse /> showMark: false,
<TreasureBox></TreasureBox> banner: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_banner_bj%402x.png'
</div> }
)
} componentDidMount() {
const _this = this
// 获取App登录信息
window['loginInfo'] = result => {
_this.loginInfo(result)
}
}
// 获取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,
})
}
render() {
const {banner} = 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"/>
</div>
<div className="banner-treasure__decorate"></div>
</div>
{/* 大咖直播 */}
<LiveRoom/>
{/* 组队开宝箱 */}
<TreasureBox/>
<YearCourse 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 { .year-index {
padding-bottom: 30px; padding-bottom: 30px;
background-color: #BC2A18; 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;
}
}
} }
\ 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: '一元拼团'
},
{
id: 'year-discount',
name: '一折专区'
},
]
};
}
componentDidMount() {
this.initNav();
window.addEventListener('scroll', this.calcNavActive)
}
componentWillUnmount () {
window.removeEventListener('scroll', this.calcNavActive);
}
initNav = () => {
const { navs } = this.state;
http.get(`${API.home}/activity/stage`).then(res => {
const { code, data } = res.data;
if(code === 200) {
// treasure_stage,宝箱阶段,0-不在活动时间,1-活动时间内
if(data.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 React, { Component } from 'react';
import CommonContainer from './../common/commonContainer/index'; import CommonContainer from './../common/commonContainer/index';
import TreasureRank from './rank'; import TreasureRank from './rank';
import TeamInfo from './team'
class TreasureBox extends Component { class TreasureBox extends Component {
render() { render() {
return ( return (
<div> <CommonContainer id="year-treasure">
<CommonContainer> <TeamInfo />
<TreasureRank /> <TreasureRank />
</CommonContainer> </CommonContainer>
</div>
) )
} }
} }
......
import React, { Component } from 'react';
import './team.scss'
import { getParam, http, SendMessageToApp, browser } 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
})
} else {
Toast.info(msg);
}
})
}
// 跳转到我的宝箱页
toYearTreasure = (close) => {
if(this.props.user.hasError) {
this.props.history.push('/passport/login');
} else {
let search = '';
if(close) {
const {removable_data, info: {removable}} = this.state;
if(removable > 0) {
let current = removable_data[0];
search = `?team_num=${current.team_num}&owner_uid=${current.captain_uid}`;
}
}
this.props.history.push(`/year/yearTreasure${search}`);
}
}
// 邀请好友组队
createTeam = () => {
if(this.props.user.hasError) {
this.props.history.push('/passport/login');
} 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;
}
}
...@@ -3,17 +3,29 @@ import './index.scss' ...@@ -3,17 +3,29 @@ import './index.scss'
import {http, SendMessageToApp, getParam} from '@/utils' import {http, SendMessageToApp, getParam} from '@/utils'
import CommonContainer from './../common/commonContainer/index' import CommonContainer from './../common/commonContainer/index'
import CourseItem from '../../../blessingPreheat/courseItem/index' import CourseItem from '../../../blessingPreheat/courseItem/index'
import {Link, withRouter} from "react-router-dom" import {withRouter} from "react-router-dom"
class YarnWish extends Component { class YarnWish extends Component {
state = { state = {
list: [] list: [],
activityStage: 1,
} }
componentDidMount() { componentDidMount() {
this.fetchCourse() this.fetchCourse()
this.getStage()
} }
componentWillUpdate() {
const {activityStage} = this.state;
if(activityStage == 1) {
document.title = `七月在线年终大回馈,人气好课免费学,精品课程1分抢!`
}else{
document.title = `七月在线年终大回馈,人气好课免费学,精品课程1分抢!`
}
}
fetchCourse = () => { fetchCourse = () => {
http.get(`${API.home}/activity/wish_course`).then(res => { http.get(`${API.home}/activity/wish_course`).then(res => {
const {code, data} = res.data const {code, data} = res.data
...@@ -24,6 +36,16 @@ class YarnWish extends Component { ...@@ -24,6 +36,16 @@ class YarnWish extends Component {
} }
}) })
} }
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) => { toCourse = (courseId) => {
...@@ -36,7 +58,7 @@ class YarnWish extends Component { ...@@ -36,7 +58,7 @@ class YarnWish extends Component {
} }
render() { render() {
const {list} = this.state const {list, activityStage} = this.state
return ( return (
<div className='yarn-wish'> <div className='yarn-wish'>
...@@ -132,10 +154,10 @@ class YarnWish extends Component { ...@@ -132,10 +154,10 @@ class YarnWish extends Component {
</CommonContainer> </CommonContainer>
: <div className="notData"> : <div className="notData">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-empty.png" alt=""/> <img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/icon-empty.png" alt=""/>
{
<p>你的心愿单目前空空如也,<br/>快去挑选更多优惠课程吧~</p> activityStage == 1 ? <p>你的心愿单目前空空如也,<br/>快去挑选更多优惠课程吧~</p>
{/*活动期间文案*/} : <p>你的心愿单没有课程哦,<br/>感兴趣的课程可在双旦主会场直接购买!</p>
{/*<p>你的心愿单没有课程哦,感兴趣的课程可在双旦主会场直接购买!</p>*/} }
</div> </div>
} }
</div> </div>
......
...@@ -233,10 +233,17 @@ export default [ ...@@ -233,10 +233,17 @@ export default [
path: '/activity/newyear-2019/landing', path: '/activity/newyear-2019/landing',
component: loadable(() => import(/* webpackChunkName: 'newyear-2019-landing'*/ '@components/activity/newyear-2019/landing/index')) component: loadable(() => import(/* webpackChunkName: 'newyear-2019-landing'*/ '@components/activity/newyear-2019/landing/index'))
}, },
// 双旦活动预热页面 // 双旦活动预热页面
{ {
path: '/year/yearIndex', path: '/year/yearIndex',
component: loadable(() => import(/* webpackChunkName: 'newyear-yearIndex' */ '@components/activity/newyear-2019/preheat/index')) 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'))
} }
, ,
// 双旦心愿单 // 双旦心愿单
......
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