Commit d08fac0a by xuzhenghua

砍价课程为空处理

parent 3d0acaa7
......@@ -1650,15 +1650,15 @@
}
},
"@videojs/http-streaming": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-1.10.3.tgz",
"integrity": "sha512-fxXtwVrQBdhOFh6GymPAPCb4utCI01Zs5fdyZgtR6FSsaz/zGmnzfNS5GvNjBi/hZviMsbNPFaOTTFMMNLNA3A==",
"version": "1.10.6",
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-1.10.6.tgz",
"integrity": "sha512-uPBuunHnxWeFRYxRX0j6h1IIWv3+QKvSkZGmW9TvqxWBqeNGSrQymR6tm1nVjQ2HhMVxVphQTUhUTTPDVWqmQg==",
"requires": {
"aes-decrypter": "3.0.0",
"global": "^4.3.0",
"m3u8-parser": "4.3.0",
"m3u8-parser": "4.4.0",
"mpd-parser": "0.8.1",
"mux.js": "5.1.3",
"mux.js": "5.2.1",
"url-toolkit": "^2.1.3",
"video.js": "^6.8.0 || ^7.0.0"
}
......@@ -9225,21 +9225,11 @@
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
},
"lodash.assign": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
},
"lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
},
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
......@@ -9270,11 +9260,6 @@
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
},
"lodash.mergewith": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
"integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="
},
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
......@@ -9348,9 +9333,9 @@
}
},
"m3u8-parser": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.3.0.tgz",
"integrity": "sha512-bVbjuBMoVIgFL1vpXVIxjeaoB5TPDJRb0m5qiTdM738SGqv/LAmsnVVPlKjM4fulm/rr1XZsKM+owHm+zvqxYA==",
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.4.0.tgz",
"integrity": "sha512-iH2AygTFILtato+XAgnoPYzLHM4R3DjATj7Ozbk7EHdB2XoLF2oyOUguM7Kc4UVHbQHHL/QPaw98r7PbWzG0gg==",
"requires": {
"global": "^4.3.2"
}
......@@ -9860,9 +9845,9 @@
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
},
"mux.js": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.1.3.tgz",
"integrity": "sha512-FhDcysLvAkO9H8ftBJ2sK1O4Rmz0AWnMS+2uqP7WjrnaAyE/ox11GEiZkRzrWIdp8at9R9qBHDqdURY3/h/xTg=="
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-5.2.1.tgz",
"integrity": "sha512-1t2payD3Y8izfZRq7tfUQlhL2fKzjeLr9v1/2qNCTkEQnd9Abtn1JgzsBgGZubEXh6lM5L8B0iLGoWQiukjtbQ=="
},
"nan": {
"version": "2.13.2",
......@@ -10025,9 +10010,9 @@
}
},
"node-sass": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz",
"integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==",
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.0.tgz",
"integrity": "sha512-W1XBrvoJ1dy7VsvTAS5q1V45lREbTlZQqFbiHb3R3OTTCma0XBtuG6xZ6Z4506nR4lmHPTqVRwxT6KgtWC97CA==",
"requires": {
"async-foreach": "^0.1.3",
"chalk": "^1.1.1",
......@@ -10036,12 +10021,10 @@
"get-stdin": "^4.0.1",
"glob": "^7.0.3",
"in-publish": "^2.0.0",
"lodash.assign": "^4.2.0",
"lodash.clonedeep": "^4.3.2",
"lodash.mergewith": "^4.6.0",
"lodash": "^4.17.15",
"meow": "^3.7.0",
"mkdirp": "^0.5.1",
"nan": "^2.10.0",
"nan": "^2.13.2",
"node-gyp": "^3.8.0",
"npmlog": "^4.0.0",
"request": "^2.88.0",
......@@ -14587,11 +14570,6 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
},
"tsml": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tsml/-/tsml-1.0.1.tgz",
"integrity": "sha1-ifghi52eJX9H1/a1bQHFpNLGj8M="
},
"tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
......@@ -14982,25 +14960,24 @@
}
},
"video.js": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/video.js/-/video.js-7.6.0.tgz",
"integrity": "sha512-A0HSKzAmcYkd1xyExqUlM6n8bkghcX54iCvW08bPvvl3UHt8d8zijuylfIWu8vo1Z8fYyk9HPOFs1i3Cldr/cw==",
"version": "7.6.5",
"resolved": "https://registry.npmjs.org/video.js/-/video.js-7.6.5.tgz",
"integrity": "sha512-r0kC9SNJhXz9th/wwbRaLVOIZTvXkF+rhFq9/FWU+e+EJClwClRCgP8STGmfrPHDXrfWiJwH9YY21JZK61vGGQ==",
"requires": {
"@babel/runtime": "^7.4.5",
"@videojs/http-streaming": "1.10.3",
"@videojs/http-streaming": "1.10.6",
"global": "4.3.2",
"keycode": "^2.2.0",
"safe-json-parse": "4.0.0",
"tsml": "1.0.1",
"videojs-font": "3.2.0",
"videojs-vtt.js": "^0.14.1",
"xhr": "2.4.0"
},
"dependencies": {
"@babel/runtime": {
"version": "7.5.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz",
"integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==",
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz",
"integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==",
"requires": {
"regenerator-runtime": "^0.13.2"
}
......
......@@ -46,13 +46,14 @@
"less-loader": "^4.1.0",
"lodash": "^4.17.15",
"mini-css-extract-plugin": "0.5.0",
"node-sass": "^4.11.0",
"node-sass": "^4.13.0",
"optimize-css-assets-webpack-plugin": "5.0.1",
"pnp-webpack-plugin": "1.2.1",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
"postcss-preset-env": "6.5.0",
"postcss-safe-parser": "4.0.1",
"prop-types": "^15.7.2",
"qrcode": "^1.3.3",
"qs": "^6.7.0",
"react": "^16.8.6",
......@@ -79,7 +80,7 @@
"swiper": "^4.5.0",
"terser-webpack-plugin": "1.2.2",
"url-loader": "1.1.2",
"video.js": "^7.6.0",
"video.js": "^7.6.5",
"web-launch-app": "^2.1.9",
"webpack": "4.28.3",
"webpack-dev-server": "3.1.14",
......
......@@ -5,5 +5,6 @@ var API = {
'passport-api': 'http://passport-test.julyedu.com',
'base-api': 'http://api-test.julyedu.com',
'record': 'record.julyedu.com:8001',
'process-api': 'ws:process-test.julyedu.com:9502'
'process-api': 'ws:process-test.julyedu.com:9502',
'm': 'http://m-test.julyedu.com',
}
......@@ -63,6 +63,9 @@ class App extends Component {
if (cookie.get('uid') && this.props.user.hasError) {
this.getUser()
}
if(location.pathname==='/passport'){
window.localStorage.setItem('binding_redirect', JSON.stringify(this.previousLocation))
}
const {pathname, state} = location
if (pathname.startsWith('/passport')) {
location.state = {
......
import React from 'react'
import ReactDOM from 'react-dom'
import './index.scss'
import classnames from 'classnames'
function ClosablePopup({
title, content, className, closable = true, close = function () {
}
} = {}) {
function unmountComponent() {
ReactDOM.unmountComponentAtNode(div)
if (div && div.parentNode) {
div.parentNode.removeChild(div)
}
}
function _close() {
let _c = close()
if (_c && _c.then) {
_c.then(() => {
unmountComponent()
})
} else {
unmountComponent()
}
}
const closablePopup = (
<div className={'closable-popup-mask'}>
<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}/>
}
</div>
</div>
)
const div = document.createElement('div')
document.body.appendChild(div)
ReactDOM.render(closablePopup, div)
return {
close: _close
}
}
export default ClosablePopup
.closable-popup-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
z-index: 999;
.popup-container {
position: absolute;
top: 165px;
left: 50%;
transform: translateX(-50%);
width: 300px;
padding: 20px 10px;
border-radius: 10px;
background: #fff;
.title {
font-size: 16px;
color: #525C65;
text-align: center;
}
.close {
position: absolute;
bottom: -74px;
left: 50%;
transform: translateX(-50%);
font-size: 36px;
color: #fff;
}
}
}
import React from 'react'
import { Modal } from 'antd-mobile'
import './index.scss'
export default function ({
amount,
limit_amount,
onCancel = () => {
},
onConfirm
}) {
const content = (
<>
<div className="end-expansion-alert-ques">
{`你的${amount}元优惠券正在膨胀中,
确定要结束膨胀吗?`}
</div>
<div className="end-expansion-alert-hint">
{`离${limit_amount}元只差一点点了!继续膨胀,优惠更多哦`}
</div>
</>
)
Modal.alert('温馨提示', content, [
{text: '再考虑下', onPress: onCancel, style: {color: '#333'}},
{text: '确定结束膨胀', onPress: onConfirm}
])
}
.am-modal {
width: 300px;
&-title {
font-size: 15px;
}
}
.end-expansion-alert {
&-ques {
width: 200px;
margin: 0 auto 20px;
text-align: center;
color: #666;
font-size: 15px;
}
&-hint {
color: #999;
font-size: 12px;
}
}
......@@ -5,8 +5,9 @@ export { default as OrderItem } from './OrderList'
export { default as HeaderBar } from './HeaderBar'
export { default as CallApp } from './CallApp'
export { default as Captcha } from './Captcha'
export { default as ClearableInput } from "./ClearableInput";
export { default as ClearableInput } from "./ClearableInput"
export { default as Loading } from './Loading'
export { default as RenderTabBar } from './renderTabBar'
export { default as Popup } from './closable-popup'
import React, {Component} from 'react'
import './index.scss'
import {http} from '@/utils'
import { Link } from "react-router-dom"
import {Toast} from "antd-mobile";
class ExpandActiveToast extends Component {
constructor(props) {
super(props);
this.state = {
expandLength: 0,
isShowExpand:true
}
}
componentDidMount() {
http.get(`${API['base-api']}/sys/deposit/notice`).then((res) => {
if (res.data.errno == 200) {
const {data} = res.data
this.setState({
expandLength: data.num
})
} else {
Toast.info(res.data.msg, 2)
}
})
}
cleseExpand = () => {
this.setState({isShowExpand: false})
}
render() {
return (
<div>
{
this.state.expandLength > 0 && this.state.isShowExpand &&
<div className="expand-active-toast">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/guanggao.png" alt=''/>
<div className="expand-toast-swiper">
<p>您有<span className="red">{this.state.expandLength}</span>待支付尾款的课程 再不支付就要过期了!</p>
</div>
<Link to='/final-deposit-order?source=1'>查看</Link>
<img
onClick={e => this.cleseExpand()}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/guanbi.png"
alt=''
/>
</div>
}
</div>
);
}
}
export default ExpandActiveToast
.expand-active-toast {
font-size: 14px;
background-color: #e8f6ff;
display: flex;
justify-content: space-between;
padding: 0 15px;
height: 33px;
line-height: 33px;
margin-bottom: 10px;
.expand-toast-swiper {
width: 240px;
overflow: hidden;
position: relative;
p {
width: 375px;
position: absolute;
-webkit-animation: scollLeft 10s linear 0s infinite;
}
}
.red {
color: #ff3131;
}
img {
width: 15px;
height: 15px;
margin-top: 9px;
}
a {
display: inline-block;
width: 44px;
height: 22px;
background: linear-gradient(90deg, #0099ff 0%, #0080ff 100%);
border-radius: 11px;
color: #fff;
font-size: 12px;
line-height: 22px;
margin-top: 5px;
text-align: center;
}
@-webkit-keyframes scollLeft {
from {
right: -100%;
}
to {
right: 100%;
}
}
@keyframes scollLeft {
from {
right: -100%;
}
to {
right: 100%;
}
}
@-moz-keyframes scollLeft {
from {
right: -100%;
}
to {
right: 100%;
}
}
@-o-keyframes scollLeft {
from {
right: -100%;
}
to {
right: 100%;
}
}
}
......@@ -11,6 +11,7 @@ import { Link } from "react-router-dom"
import { Toast } from 'antd-mobile'
import { connect } from "react-redux";
import TopSwiper from './TopSwiper'
import ExpandActiveToast from './expandActiveToast'
// const animateTypes = Swiper.animateTypes
......@@ -135,6 +136,10 @@ class Index extends Component {
/>
</div>
<div className='zw_height'></div>
<ExpandActiveToast/>
<div className='index-swiper'>
{
this.state.banner && this.state.banner.length > 0 &&
......
......@@ -38,8 +38,11 @@
}
}
.zw_height {
height: 44px;
}
.index-swiper {
margin-top: 44px;
height: 168px;
.swiper-container {
......
import React, { Component } from 'react'
import {connect} from "react-redux";
import { http, getParam } from '@/utils';
import cookie from 'js-cookie'
import './index.scss';
import {Toast} from "antd-mobile";
import jsCookie from 'js-cookie';
class Activity extends Component {
constructor(props) {
super(props);
this.state = {
'butText': '立即领取'
}
}
componentWillMount() {
jsCookie.set('blessing_invite_uid', getParam('shareuid'), {domain: '.julyedu.com', expires: 30});
jsCookie.set('blessing_invite_code', getParam('inviteCode'), {domain: '.julyedu.com', expires: 30});
if(cookie.get('uid')) {
this.setState(()=>({
butText: '已领取,去使用'
}));
}
}
getGift = () => {
if(this.props.user.hasError) {
this.props.history.push('/passport', {from: this.props.location.pathname});
} else {
this.props.history.push('/blessingPreheat');
}
}
render() {
const {butText} = this.state;
return (
<div className="activity__con">
<div className='banner__con'></div>
<div className='content__con'>
<div className="button__get" onClick={this.getGift}>{butText}</div>
</div>
</div>
)
}
}
export default connect(
state => ({user: state.user}),
null
)(Activity);
.activity__con {
width: 100%;
height: 100vh;
background-color: #5327FA;
overflow: auto;
.banner__con {
width: 100%;
height: 170px;
background: url('./images/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-size: 100% 100%;
position: relative;
.button__get {
width:220px;
height:40px;
background:rgba(253,203,5,1);
border-radius:10px;
font-size:18px;
font-weight:400;
color:rgba(246,53,28,1);
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 14px;
letter-spacing: 2px;
text-align: center;
line-height: 40px;
}
}
.invite__content {
color:rgba(255,255,255,1);
font-weight:400;
.content__one {
width: 100%;
padding: 0 50px;
font-size: 14px;
display: flex;
justify-content: center;
align-items: center;
height: 20px;
margin-bottom: 12px;
p {
display: flex;
align-items: center;
justify-content: center;
}
.img__con {
width: 88px;
height: 16px;
background: url('./images/value.png') center center no-repeat;
background-size: 100% 100%;
margin-left: 4px;
}
}
.content__two {
height:16px;
line-height: 16px;
font-size:16px;
text-align: center;
text-align-last: center;
margin-bottom: 14px;
}
.box__out {
width:345px;
height:106px;
background:linear-gradient(to bottom,rgba(255,169,67,1) 0%,rgba(250,94,39,1) 100%);
border-radius:10px;
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
}
.box__middle {
width:333px;
height:94px;
background:rgba(255,255,255,1);
box-shadow:0px 1px 3px 0px rgba(133,75,2,0.1);
border-radius:8px;
display: flex;
justify-content: center;
align-items: center;
}
.box__inner {
width:327px;
height:88px;
background:rgba(255,223,4,1);
border:1px solid rgba(253,184,46,1);
box-shadow:0px 1px 3px 0px rgba(133,75,2,0.1);
border-radius:6px;
color: #F24000;
font-size: 16px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
p {
font-size: 16px;
line-height: 16px;
margin-top: 12px;
color:rgba(242,64,0, .8);
font-weight: 400;
}
p.hot__value {
color: #FD3D24;
font-size: 20px;
font-weight:500;
line-height: 20px;
}
.hot__progress {
display: flex;
flex-direction: row;
max-height: 8px;
width: 280px;
align-items: center;
justify-content: center;
margin-top: 10px;
.progress__bar {
width:210px;
height:6px;
background:rgba(255,255,255,1);
border-radius:3px;
position: relative;
}
span {
display: flex;
justify-content: center;
align-items: center;
width: 48px;
height: 20px;
color: #5327FA;
font-size: 20px;
transform: scale(0.5);
}
.progress__point {
position: absolute;
height: 6px;
border-radius: 3px;
background:linear-gradient(90deg,rgba(83,39,250,1) 0%,rgba(168,39,250,1) 100%);
}
}
}
.but__con {
width:216px;
height:40px;
background:rgba(57,0,201,.5);
border-radius:8px;
margin: 20px auto 0;
display: flex;
justify-content: center;
align-items: center;
.button__content {
width:210px;
height:36px;
background:rgba(255,255,255,1);
border-radius:6px;
font-size:16px;
font-weight:400;
color:rgba(57,0,201,1);
display: flex;
justify-content: center;
align-items: center;
}
}
.list__title {
height:14px;
line-height: 14px;
font-size:14px;
font-weight:400;
color:rgba(255,255,255,1);
width: 240px;
background: url('./images/yaoqh_bj.png') center center no-repeat;
background-size: 100% 50%;
text-align: center;
text-align-last: center;
margin: 30px auto 10px;
}
.show__new {
font-size: 12px;
color: #A993FD;
text-align: center;
text-align-last: center;
}
.list__con {
width: 346px;
margin: 14px auto;
border: 1px solid rgba(255,255,255, .5);
// min-height: 190px;
border-radius:10px;
display: flex;
flex-wrap: wrap;
padding: 0 15px;
.user__item-info {
width: 156px;
height: 46px;
display: flex;
justify-content: flex-start;
align-items: center;
.item__con {
width: 100%;
height: 40px;
display: flex;
justify-content: flex-start;
align-items: center;
margin-left: 6px;
margin-right: 0;
border-bottom: 1px rgba(255, 255, 255, 0.6) dashed;
}
&:nth-child(2n+1) {
border-right: 1px solid rgba(169,147,253,1);
.item__con {
margin-right: 6px;
margin-left: 0;
}
}
.user_avatar {
width: 22px;
height: 22px;
border-radius: 50%;
margin-right: 10px;
}
.user_name {
width: 114px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-size: 12px;
font-weight: 400;
color: #fff;
}
}
.item__con-only {
width: 100%;
&:nth-child(2n+1) {
border-right: none;
}
.item__con {
width: 100%;
}
}
}
}
.share__mark {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .4);
.share__tip {
width:290px;
height:62px;
background:rgba(255,255,255,1);
border-radius:10px;
display: flex;
justify-content: center;
align-items: center;
color: #525C65;
font-size: 16px;
position: absolute;
top: 78px;
left: 50%;
transform: translateX(-50%);
}
.share__row {
width: 60px;
height: 44px;
background: url('./images/throw_icon.png') center center no-repeat;
background-size: 100% 100%;
position: absolute;
right: 15px;
top: 10px;
}
}
}
\ No newline at end of file
import React, { Component } from 'react';
import {connect} from "react-redux"
import './index.scss';
import { http, getParam, is_weixin, wxShare, getC, SendMessageToApp } from '@/utils';
import {Toast} from "antd-mobile";
import jsCookie from 'js-cookie';
class Invite extends Component {
constructor(props) {
super(props);
this.state = {
isWeiXin: false,
showTip: false,
hotValue: 0,
hot_schedule: '',
userList: [],
inviteCode: '',
}
}
componentWillMount() {
let uid = jsCookie.get('uid');
let shareuid = getParam('shareuid');
if(uid === shareuid) {
} else {
if(getParam('new')) {
this.props.history.push(`/activity?shareuid=${shareuid}&inviteCode=${getParam('inviteCode')}`);
}
}
}
componentDidMount() {
if(!this.props.user.hasError) {
this.getUserList();
this.getHotValue();
this.getInviteCode();
}
}
componentWillReceiveProps(nextProps) {
console.log('componentWillReceiveProps');
if(!nextProps.user.hasError) {
this.getUserList();
this.getHotValue();
this.getInviteCode();
}
}
getUserList = () => {
http.get(`${API.home}/sys/user/invite/list`).then(res => {
let {code, data, msg} = res.data;
if(code === 200) {
this.setState({
userList: data
});
} else {
Toast.info(msg, 2);
}
});
}
getHotValue = () => {
http.get(`${API.home}/sys/user/hot/value`).then(res => {
let {code, data, msg} = res.data;
if(code === 200) {
this.setState({
hot_schedule: data.hot_schedule,
hotValue: data.hot_value
});
} else {
Toast.info(msg, 2);
}
});
}
getInviteCode = () => {
http.get(`${API.home}/sys/user/invite/link`).then(res => {
let {code, data, msg} = res.data;
if(code === 200) {
let inviteCode = data.blessing_invite_code;
if(is_weixin()) {
wxShare({
title: 'AI充电节,积福气享1折秒课,超10万元奖品来就送!!',
desc: '把这门超5万人报名的【Python基础入门 升级版】课程送给你,附200元红包,请笑纳!--七月在线',
link: encodeURI(location.origin + `/invite?shareuid=${jsCookie.get('uid')}&new=1&inviteCode=${inviteCode}`),
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/index-share-img.png',
});
}
this.setState(()=>({
inviteCode: inviteCode
}))
}else if(code === 4030 || code === 4040) {
history.push('/passport');
}else{
Toast.info(msg, 2);
}
});
}
inviteFriends = () => {
const { user, history } = this.props;
const {inviteCode} = this.state;
// 未登录先去登录
if (getParam('version')) {
if(user.hasError) {
SendMessageToApp("toLogin");
}else {
let data = {
title: 'AI充电节,积福气享1折秒课,超10万元奖品来就送!!',
desc: '把这门超5万人报名的【Python基础入门 升级版】课程送给你,附200元红包,请笑纳!--七月在线',
link: API.m + `/invite?shareuid=${jsCookie.get('uid')}&new=1&inviteCode=${inviteCode}`,
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/index-share-img.png',
}
SendMessageToApp("toShare", data)
}
}else {
if(user.hasError) {
history.push('/passport');
}else {
if(is_weixin()) {
history.push(`/invite?shareuid=${jsCookie.get('uid')}&new=1&inviteCode=${inviteCode}`);
wxShare({
title: 'AI充电节,积福气享1折秒课,超10万元奖品来就送!!',
desc: '把这门超5万人报名的【Python基础入门 升级版】课程送给你,附200元红包,请笑纳!--七月在线',
link: encodeURI(location.origin + `/invite?shareuid=${jsCookie.get('uid')}&new=1&inviteCode=${inviteCode}`),
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/index-share-img.png',
});
this.setState({
showTip: true,
isWeiXin: true,
});
}else{
history.push(`/invite?shareuid=${jsCookie.get('uid')}&new=1&inviteCode=${inviteCode}`);
this.setState({
showTip: true,
});
}
}
}
}
closeMark = () => {
this.setState({
showTip: false,
});
}
render() {
let {userList, showTip, hotValue, hot_schedule, isWeiXin} = this.state;
return (
<div className="activity__con">
<div className='banner__con'></div>
<div className="invite__content">
<div className="content__one">
<p>邀请好友注册,每增加1人可</p>
<div className="img__con"></div>
</div>
<div className="content__two">
福气值越高,热力值越高,中奖概率越大!
</div>
<div className="box__out">
<div className="box__middle">
<div className="box__inner">
<p>当前中奖热力值:</p>
<p className="hot__value">{hotValue}</p>
<div className="hot__progress">
<div className="progress__bar">
<div className="progress__point" style={{'width': hot_schedule}}></div>
</div>
</div>
</div>
</div>
</div>
<div className="but__con">
<div className="button__content" onClick={this.inviteFriends}>
立即邀请
</div>
</div>
{
userList.length > 0 ? (
<>
<div className="list__title">
<span>邀请好友列表</span>
</div>
<p className="show__new">(仅显示新用户)</p>
</>
) : (null)
}
{
userList.length > 0 ? (
<div className="list__con">
{
userList.length === 1 && userList.map((item, index) => {
return (
<div className="user__item-info item__con-only" key={index}>
<div className="item__con">
<img className="user_avatar" src={item.head_image} />
<div className="user_name">{item.user_name}</div>
</div>
</div>
)
})
}
{
userList.length > 1 && userList.map((item, index) => {
return (
<div className="user__item-info" key={index}>
<div className="item__con">
<img className="user_avatar" src={item.head_image} />
<div className="user_name">{item.user_name}</div>
</div>
</div>
)
})
}
</div>
) : (
null
)
}
</div>
{
showTip && (
<div className="share__mark" onClick={this.closeMark}>
<div className="share__tip">
立即分享给好友增加中奖概率
</div>
{
isWeiXin ? (
<div className="share__row"></div>
) : (
null
)
}
</div>
)
}
</div>
)
}
}
export default connect(
state => ({user: state.user}),
null
)(Invite);
import React, { Component } from 'react'
import './index.scss'
import { getParam, http } from '@/utils'
import { WithFullSize } from "@/HOCs"
class PrizeWinnerList extends Component {
state = {
list: [],
title: '',
}
componentDidMount() {
http.get(`${API.home}/sys/activity/lottery_names/${getParam('tid')}`)
.then(res => {
const {data} = res
if (data.code == 200) {
const {data: response} = data
this.setState({
title: response.title,
list: response.list
})
}
})
}
render() {
const {title, list} = this.state
return (
<div id={'prize-winner-list'}>
<div className="banner">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/prize-winner-list-banner.png" alt=""
className="banner"/>
</div>
<h1>
<img className={'icon'}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/title-decorate-left.png" alt=""/>
<span>{title}</span>
<img className={'icon'}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/title-decorate-right.png" alt=""/>
</h1>
<ul>
<li className={'head title'}>
<div className="code">中奖码</div>
<div className="user-name">用户名称</div>
<div className="prize">奖品名称</div>
</li>
{
list.map(item => (
<li key={item.code}>
<div className="code">{item.code}</div>
<div className="user-name">{item.name}</div>
<div className="prize">{item.prize}</div>
</li>
))
}
</ul>
</div>
)
}
}
export default WithFullSize(PrizeWinnerList)
#prize-winner-list {
height: 100%;
background: #5327fa;
.banner {
width: 100%;
height: 168px;
margin-bottom: 30px;
img {
width: 100%;
height: 100%;
}
}
h1 {
font-size: 14px;
color: #FEFDC7;
text-align: center;
margin-bottom: 15px;
span {
margin: 0 12px;
}
.icon {
width: 25px;
height: 12px;
}
}
ul {
width: 355px;
height: 316px;
margin: 0 auto;
background: rgba(57, 0, 201, 1);
border: 1px solid rgba(89, 112, 255, 1);
border-radius: 4px;
& li:nth-of-type(2n+1) {
background: #3900C9;
}
& li:nth-of-type(2n) {
background: #4200EB;
}
li {
height: 44px;
color: #FAF9E1;
display: flex;
text-align: left;
line-height: 44px;
}
.title{
color: #95FBCA;
text-align: center;
}
.code, .user-name {
width: 110px;
padding-left: 8px;
}
.user-name{
text-align: center;
}
.prize {
width: 135px;
padding-right: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
import React, {Component} from 'react';
import {http, getParam, SendMessageToApp} from '@/utils';
import listFrame from './../listFrame/index';
import './index.scss';
import {Toast} from "antd-mobile"
import {connect} from "react-redux";
import {Link, withRouter} from "react-router-dom"
class ReserveCourse extends Component {
constructor(props) {
super(props);
this.state = {
courseData: [],
isShowMore: false
};
}
componentDidMount() {
this.fetchAICourse();
}
shouldComponentUpdate(nextProps, nextState, nextContext) {
if(this.props.isApp !== nextProps.isApp) {
this.fetchAICourse();
return false;
}
return true;
}
fetchAICourse = () => {
http.get(`${API.home}/sys/pre_coursee`).then(res => {
const {code, data, msg} = res.data;
if (code === 200) {
this.setState({
courseData: JSON.stringify(data) == '{}' ? []:data.filter((item, index) => index < 4),
courseDataAll: data
})
} else {
Toast.info(msg, 2);
}
});
}
// 立即付定金
expandPaydj = (courseId) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
if (!getParam('version')) {
this.props.history.push('/passport/login')
} else {
SendMessageToApp("toLogin");
}
} else {
if (!getParam('version')) {
this.props.history.push(
`/deposit-order?oid=${courseId}&source=${2}`,
{
id: courseId,
isexpand: 1,
sourcenum: 2
}
)
} else {
SendMessageToApp("earnestMoney", courseId);
}
}
}
// 立即付尾款
expandPaywk = (courseId, time,day) => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
if (!getParam('version')) {
this.props.history.push('/passport/login')
} else {
SendMessageToApp("toLogin");
}
} else {
let timeStamp = Date.parse(new Date()) / 1000;
if (timeStamp >= time) {
if (!getParam('version')) {
this.props.history.push(
'/final-deposit-order?source=1',
{
id: courseId,
sourcenum: 1
}
)
} else {
SendMessageToApp("TailMoney");
}
} else {
Toast.info("付尾款时间将在" + day + "开启", 2);
}
}
}
// 去学习
tostudy = (courseId) => {
if (!getParam('version')) {
this.props.history.push(`/getDetail?id=${courseId}`)
} else {
let data = {
courseId: courseId,
type: 0 // 正常跳课程详情页type:0,积福气浏览课程详情页-没有浏览过type:1 已浏览过type:2
}
SendMessageToApp("toCourse", data);
}
}
// 查看更多
showMoreData = () => {
this.setState({
isShowMore: !this.state.isShowMore,
courseData: this.state.isShowMore ? this.state.courseDataAll.filter((item, index) => index < 4) : this.state.courseDataAll,
})
}
render() {
const {courseData, isShowMore} = this.state;
return (
<div className='reserve-course-module'>
<CourseList courseData={courseData}
expandPaydj={this.expandPaydj}
expandPaywk={this.expandPaywk}
tostudy={this.tostudy}/>
<button className="more-button" onClick={this.showMoreData}>
{isShowMore ? '收起' : '展开更多'}
</button>
</div>
)
}
}
function CourseList(props) {
const {courseData, expandPaydj, expandPaywk, tostudy} = props
return (
<div className="course-list">
<ul>
{
courseData.map((item, index) => {
return (
<li className="course-item-box" key={index}>
<a onClick={() => tostudy(item.course_id)}>
<div className="top">
<div className="square">
<p className="circular">
到手最低¥<span>{Number(item.price) - Number(item.deduction_amount) - Number(item.limit_amount)}</span>
</p>
</div>
<img className="course-img" src={item.image_name} alt=""/>
</div>
</a>
<p className="count-price">
=原价¥{item.price}
<span>-抵扣¥<i>{item.deduction_amount}</i></span>
<span>-膨胀券¥<i>{item.limit_amount}</i></span>
</p>
<div className="btn">
{
item.is_buy === 0 &&
<button className="to-expand-buy1"
onClick={() => expandPaydj(item.course_id)}>立即付定金</button>
}
{
item.is_buy === 1 &&
<button
className="to-expand-buy2"
onClick={() => expandPaywk(item.course_id, item.start_timestamp,item.final_start_time)}
>立即付尾款</button>
}
{
item.is_buy === 2 &&
<button className="to-study"
onClick={() => tostudy(item.course_id)}>开始学习</button>
}
</div>
</li>
)
})
}
</ul>
</div>
)
}
export default listFrame(connect(
state => ({
user: state.user
}),
)(withRouter(ReserveCourse)))
.reserve-course-module {
margin: 20px 15px 0 20px;
padding-bottom: 5px;
.course-list {
ul {
display: flex;
justify-content: space-between;
flex-direction: row;
flex-wrap: wrap;
.course-item-box {
width: 48%;
padding: 4px;
background-color: #fff;
border-radius: 2px;
margin-bottom: 15px;
text-align: left;
.top {
width: 100%;
height: 108px;
position: relative;
.course-img {
width: 100%;
height: 108px;
}
.square {
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/course-label-bg.png");
background-repeat: no-repeat;
background-size: cover;
width: 60px;
height: 60px;
position: absolute;
left: 0;
bottom: 0;
.circular {
height: 100%;
width: 100%;
color: #fff;
padding-top: 15px;
text-align: left;
padding-left: 5px;
span {
font-size: 16px;
margin-left: 3px;
}
}
}
}
.count-price {
text-align: left;
color: #555;
margin-top: 8px;
line-height: 15px;
span {
color: #FF4000;
i {
font-size: 16px;
font-style: normal;
margin-left: 3px;
}
}
}
.btn {
width: 100%;
padding: 0 5px;
margin-top: 8px;
margin-bottom: 5px;
button {
width: 100%;
height: 24px;
border-radius: 2px;
font-size: 12px;
color: #fff;
border: none;
}
.to-expand-buy1 {
background: linear-gradient(-90deg, #7800FF 0%, #FF4BF0 100%);
}
.to-expand-buy2 {
background: linear-gradient(-90deg, #FF8C1B 0%, #FF3B05 100%);
}
.to-study {
background: linear-gradient(-90deg, #2ECEF0 0%, #2D56F0 100%);
}
}
}
}
}
.more-button {
display: block;
width: 100px;
height: 27px;
margin: 5px auto 15px;
border: 1px solid #fff;
border-radius: 14px;
font-size: 13px;
font-weight: 300;
color: #fff;
background-color: transparent;
cursor: pointer;
outline: none;
}
}
import React, { Component } from 'react';
import { isEmpty } from 'lodash';
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;
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">
<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
// 地址弹窗
.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;
width: 120px;
height: 34px;
margin: 8px auto 0;
border-radius: 17px;
border-style: none;
background-color: rgba(82, 92, 101, 0.3);
font-size: 15px;
font-weight: 500;
color: rgba(255, 255, 255, 1);
line-height: 34px;
cursor: pointer;
outline: none;
&[data-status="do"] {
background-color: #0099FF;
}
}
\ No newline at end of file
import React, { Component } from 'react';
import './index.scss';
class Banner extends Component {
navTop = 183
prevY = 0
state = {
navs: [
{
text: '积福气',
id: 'lucky-value'
},
{
text: '幸运大抽奖',
id: 'lucky-draw'
},
{
text: '预付定金',
id: 'deposit'
},
{
text: '精品特惠',
id: 'best-courses'
},
{
text: 'AI测试',
id: 'ai-test'
},
{
text: '大咖直播',
id: 'live'
},
],
index: 0,
}
// componentDidMount() {
// window.addEventListener('scroll', throttle(this.calcNavActive, 100))
// }
// componentWillUnmount() {
// window.removeEventListener('scroll', throttle(this.calcNavActive, 100))
// }
// calcNavActive = () => {
// const {navs, index} = this.state
// const y = window.scrollY
// let swipeDirection = y > this.prevY ? 'up' : 'down'
// let _index
// if (swipeDirection === 'up') {
// _index = (index + 1) >= navs.length ? index : index + 1
// } else {
// _index = (index - 1) <= 0 ? 0 : index - 1
// }
// let el = document.querySelector(`#${navs[_index].id}`)
// let nav = document.querySelector('#main-nav')
// if(el) {
// let top = el.offsetTop
// if (y <= this.navTop) {
// nav.classList.remove('fixed')
// } else {
// !nav.classList.contains('fixed') && nav.classList.add('fixed')
// }
// if (swipeDirection === 'up') {
// if (y + 30 + 30 >= top) {
// this.setState({
// index: _index
// })
// }
// } else {
// if (y + 30 + 20 <= top) {
// this.setState({
// index: _index
// })
// }
// }
// this.prevY = y
// }
// }
// toSection = (i, e) => {
// e.preventDefault()
// let top = document.querySelector(`#${this.state.navs[i].id}`).offsetTop
// this.setState({
// index: i
// })
// window.scrollTo({
// top: top - 60,
// left: 0
// })
// }
render() {
const { toSection, navs, index } = this.props;
return (
<div id={'main-banner'}>
<div className="banner"></div>
<nav id={'main-nav'}>
<ul>
{
navs.map((item, i) => {
return (
<li key={i} className={index === i ? 'active' : ''}>
<a href={`#${item.id}`} onClick={(e) => toSection(i, e)}>{item.text}</a>
</li>
)
})
}
</ul>
</nav>
</div>
)
}
}
export default Banner
#main-banner{
overflow: auto;
.banner{
width: 375px;
height: 183px;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/banner.png") no-repeat;
background-size: contain;
}
#main-nav{
position: absolute;
top: 183px;
width: 100%;
margin-bottom:30px;
&.fixed{
position: fixed;
top: 0;
z-index: 100;
}
ul{
background: #3900C9;
display: flex;
}
li{
flex: 1;
width: 63px;
height: 40px;
font-size: 11px;
color: #fff;
text-align: center;
line-height: 40px;
&.active{
background: #FF42F9;
}
}
}
}
.collect-blessing {
padding-bottom: 30px;
}
.collect-blessing__item {
display: flex;
align-items: center;
position: relative;
width: 335px;
height: 60px;
margin: 20px auto 0;
border-radius: 5px;
background-color: #fff;
}
.collect-blessing__num {
position: absolute;
top: 0;
left: 0;
width: 25px;
height: 25px;
padding-left: 6px;
box-sizing: border-box;
font-size: 12px;
font-style: normal;
font-weight: bold;
color: #FFFFFD;
line-height: 21px;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/blessing-number-bg.png');
background-size: cover;
}
.collect-blessing__title {
flex: 1;
padding: 0 8px 0 24px;
font-size: 12px;
color: #333;
line-height: 18px;
}
.collect-blessing__content {
display: inline-flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 64px;
height: 100%;
border-style: none;
border-radius: 5px;
font-size: 12px;
color: #fff;
text-align: center;
background: linear-gradient(-40deg,rgba(255,75,240,1) 0%,rgba(162,0,255,1) 100%);
i {
font-style: normal;
font-size: 12px;
}
&[data-layout="column"] {
flex-direction: column;
}
&[data-status="done"] {
background: rgba(82,92,101,.3);
}
}
.collect-blessing__label {
margin: 0 0 8px;
}
.collect-blessing__share {
display: flex;
align-items: center;
justify-content: center;
}
.collect-blessing__share-button {
display: block;
width: 20px;
height: 11px;
border-style: none;
background-color: transparent;
background-size: auto 100%;
background-repeat: no-repeat;
background-position: center;
&[data-type="qq"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/qq-icon.png');
}
&[data-type="wechat"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/wechat-icon.png');
}
&[data-type="weibo"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/icon-weibo.png');
}
}
.activity__over {
font-size:12px;
font-weight:400;
color:rgba(255,243,240,1);
margin: 10px auto;
text-align: center;
}
.login__btn {
width:34px;
height:18px;
background:linear-gradient(0deg,rgba(255,67,2,1), rgba(255,132,0,1));
border-radius:3px;
color: #FFF;
font-size: 12px;
font-weight: 400;
text-align: center;
margin-right: 12px;
}
.text_nologin {
font-size:16px;
font-weight:600;
color:rgba(255,243,240,1);
margin-left: 12px;
}
.rules__item {
background: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/fuqi_bj1.png') center center no-repeat;
background-size: 100% 100%;
width: 336px;
padding: 18px 18px 10px 18px;
margin: 10px auto 0;
box-sizing: border-box;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
min-height: 106px;
.item__left {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 90px;
height: 100%;
padding-right: 10px;
.tip__bubble {
position: relative;
margin-bottom: 10px;
.tip__text {
width: 54px;
height: 22px;
background:linear-gradient(90deg,rgba(245,175,172,1) 0%,rgba(241,226,229,1) 100%);
border-radius:3px;
font-weight:400;
line-height: 22px;
text-align: center;
color:rgba(255,67,2,1);
}
.tip__style {
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid #F3C9C9;
position: absolute;
bottom: -6px;
left: 50%;
transform: translateX(-50%);
}
}
.range__number {
font-size:16px;
font-weight:500;
color:rgba(255,67,2,1);
}
}
.item__right {
border-left: 1px dashed rgba(255,255,255, .5);
flex: 1 1 auto;
font-size:12px;
font-weight:400;
color:rgba(242,240,250,1);
line-height:15px;
padding: 8px 0 8px 20px ;
p {
margin-bottom: 10px;
line-height: 1;
&:last-child {
margin-bottom: 0;
}
span {
font: size 12px;
font-weight:400;
color:rgba(255,223,4,1);
line-height:15px;
}
}
}
}
\ No newline at end of file
import React, { Component } from 'react';
import './index.scss';
class CourseItem extends Component {
render() {
const { image,toCourse,id} = this.props;
return (
<div className="course-container">
<div className="course__cover">
<img src={image} alt="cover" onClick={() => toCourse(id)}/>
</div>
{this.props.children}
</div>
);
}
}
export default CourseItem;
\ No newline at end of file
.course-container {
width: 168px;
// height: 156px;
margin: 0 4px 15px;
border-radius: 2px;
background-color: #fff;
}
.course__cover {
height: 108px;
padding: 4px 4px 0;
overflow: hidden;
img {
display: block;
width: 100%;
height: 100%;
}
}
\ No newline at end of file
.boutique-course {
padding-bottom: 5px;
}
.course-button {
display: block;
width: 138px;
height: 24px;
margin: 0 auto;
border-radius: 2px;
font-size: 12px;
color: #fff;
text-align: center;
line-height: 24px;
background: linear-gradient(90deg,rgba(255,140,27,1) 0%,rgba(255,59,5,1) 100%);
&[data-type="study"] {
background: linear-gradient(269deg,rgba(7,240,255,1) 0%,rgba(0,153,255,1) 100%);
}
}
.coupon-course__footer {
padding: 10px 0;
.course-button {
//margin: 5px auto 0;
}
}
.cent-course__footer {
padding: 15px 0 10px;
}
.coupon-course__button {
display: flex;
align-items: center;
width: 138px;
height: 34px;
margin: 0 auto;
font-size: 12px;
color: #fff;
text-align: center;
line-height: 1;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/coupon-bg-0.png');
background-repeat: no-repeat;
background-size: cover;
}
.coupon-course__button--receive {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/coupon-bg-1.png');
}
.coupon-course__button-price {
flex: 1;
display: inline-flex;
flex-direction: column;
justify-content: center;
align-items: center;
i {
font-size: 8px;
font-style: normal;
}
}
.coupon-course__button-label {
width: 86px;
}
.more-button {
display: block;
width: 100px;
height: 27px;
margin: 0 auto 15px;
padding: 0;
border: 1px solid #fff;
border-radius: 14px;
font-size: 13px;
font-weight: 300;
color: #fff;
line-height: 27px;
background-color: transparent;
cursor: pointer;
outline: none;
}
.ai-course__subtitle {
width: 83px;
height: 24px;
margin: 0 auto 15px;
border-radius: 12px;
font-size: 14px;
font-weight: 500;
color: #fff;
text-align: center;
line-height: 24px;
background: linear-gradient(-90deg,rgba(46,206,240,1) 0%,rgba(45,86,240,1) 100%);
}
[data-layout="row"] {
display: flex;
flex-wrap: wrap;
}
\ No newline at end of file
import React, { Component } from 'react';
import classnames from 'classnames';
import { http, SendMessageToApp } from "@/utils";
import './index.scss';
import { getParam } from '../../../utils';
class CoursePopup extends Component {
constructor(props) {
super(props);
this.state = {
courseList: []
};
}
componentDidMount() {
this.fetchCourseData();
}
fetchCourseData = () => {
Promise.all([
http.get(`${API.home}/sys/browse/blessing/courses`),
http.get(`${API.home}/sys/user/blessing`)
]).then(res => {
const { code, data } = res[0].data;
const doneCourse = res[1].data.data.today_browsed_courses || [];
if(code === 200) {
this.setState({
courseList: data.map(item => {
if(doneCourse.some(id => id == item.course_id)) {
return Object.assign({}, item, {
blessing: 2
});
}
return item;
})
});
}
});
}
toCourseDetail = (item) => {
console.log(this.props);
const {isLogin, history, toLogin} = this.props;
// to={`/detail?id=${item.course_id}&ac=11`}
if(isLogin) {
if(!getParam('version')) {
history.push(`/detail?id=${item.course_id}&ac=11`);
}else{
let type = 0;
if(item.blessing) {
type = 2;
}else{
type = 1;
}
let data = {
courseId: item.course_id,
type: type // 正常跳课程详情页type:0,积福气浏览课程详情页-没有浏览过type:1 已浏览过type:2
}
SendMessageToApp("toCourse", data);
}
}else{
toLogin();
}
}
render() {
const { courseList } = this.state;
const { handleToHide } = this.props;
return (
<div className="course-popup__container">
<div className="course-popup">
<h2 className="course-popup__title">指定课程</h2>
<div className="course-popup__list">
{
courseList.map(item => (
<span
className={classnames("course-popup__item", {
"course-popup__item--active": item.blessing
})}
key={item.course_id}
onClick={()=>{this.toCourseDetail(item)}}
>
<span className="course-popup__name">{item.course_title}</span>
{
item.blessing &&
<span>+2</span>
}
</span>
))
}
</div>
</div>
<i className="iconfont iconiconfront-2" onClick={handleToHide}></i>
</div>
);
}
}
export default CoursePopup;
\ No newline at end of file
.course-popup__container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
.iconfont {
margin: 16px 0 0;
font-size: 28px;
color: #fff;
cursor: pointer;
}
}
.course-popup {
width: 300px;
height: 275px;
padding: 20px 0 0;
border-radius: 10px;
box-sizing: border-box;
background-color: #fff;
}
.course-popup__title {
margin: 0 0 20px;
font-size: 16px;
font-weight: 500;
color: #525C65;
text-align: center;
line-height: 1;
}
.course-popup__list {
height: 190px;
padding: 0 15px;
overflow-y: auto;
}
.course-popup__item {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 30px;
padding: 0 10px;
border-radius: 4px;
box-sizing: border-box;
color: rgba(82, 92, 101, .6);
background-color: #E7EDF2;
&:nth-child(n+2) {
margin-top: 10px;
}
&:hover {
color: #fff;
background-color: rgba(0, 153, 255, .6);;
}
}
.course-popup__item--active {
.course-popup__name {
color:rgba(82,92,101,.6);
}
}
.course-popup__name {
width: 200px;
font-size: 12px;
color:rgba(82,92,101,1);
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
\ No newline at end of file
#blessing-preheat {
background: #5327FA;
}
.timeline-share{
height: 215px;
padding-bottom: 30px;
.title{
margin-bottom: 20px;
}
.content{
text-align: center;
.qr-code{
width: 120px;
height: 120px;
}
}
}
.test__record {
width: 106px;
height: 26px;
border:1px solid rgba(255,246,4,1);
border-radius:13px;
font-size:14px;
font-weight:400;
color:rgba(255,246,4,1);
margin: 10px auto 14px;
display: flex;
justify-content: center;
align-items: center;
}
.sort__rules {
font-size:12px;
font-weight:400;
color:rgba(255,255,255,1);
text-align: center;
text-align-last: center;
}
.join-lottery {
background: #5327FA;
text-align: center;
.title {
color: #fff;
margin-bottom: 15px;
}
.text {
width: 275px;
height: 248px;
padding: 36px 30px 0;
margin-bottom: 10px;
text-align: center;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/join-lottery-bg.png");
background-size: contain;
font-size: 14px;
.code {
color: #FF0000;
margin-bottom: 8px;
}
.time, .hint {
font-size: 12px;
color: #525C65;
}
.time {
margin-bottom: 20px;
}
.hint{
color: rgba(82, 92, 101, .8);
margin-bottom: 10px;
text-align: left;
}
.qr-code {
width: 90px;
height: 90px;
}
}
button {
width: 133px;
height: 30px;
background: #fff;
border-radius: 15px;
font-size: 14px;
color: #5327FA;
-webkit-appearance: none;
outline: none;
border: none;
}
}
.invite-popup {
.content {
display: flex;
flex-flow: column;
align-items: center;
margin-top: 29px;
.qr-code {
width: 120px;
height: 120px;
margin-bottom: 20px;
}
button {
width: 133px;
height: 30px;
background: rgba(83, 39, 250, 1);
border-radius: 15px;
font-size: 14px;
color: #fff;
-webkit-appearance: none;
outline: none;
border: none;
}
}
}
// 幸运大抽奖--预热
.luck-draw__tip {
margin: 0 0 10px;
font-size: 12px;
color: #FFF604;
text-align: center;
}
.luck-draw__button {
display: block;
width: 106px;
height: 26px;
margin: 0 auto 15px;
padding: 0;
border: 1px solid #FFF604;
border-radius: 13px;
box-sizing: border-box;
font-size: 13px;
color: #FFF604;
text-align: center;
line-height: 24px;
background-color: transparent;
cursor: pointer;
outline: none;
}
import React, { Component } from 'react'
import './index.scss'
import listFrame from './../listFrame/index';
import { http, SendMessageToApp} from "@/utils"
class LevelTest extends Component {
constructor(props) {
super(props);
this.state = {
testNumber: '',
number: 1,
prizeListUrl: [
{
url:
"https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/AIExam/top1.png"
},
{
url:
"https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/AIExam/top2.png"
},
{
url:
"https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/AIExam/top3-4.png"
},
{
url:
"https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/AIExam/top5-7.png"
},
{
url:
"https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/AIExam/top8-10.png"
}
],
}
}
componentDidMount() {
const {isLogin} = this.props;
if(isLogin) {
http.get(`${API.home}/sys/ai_test/get_user_testinfo`).then(res => {
let {code, data: {user_test_total, user_residue_number}} = res.data;
if(code === 200) {
this.setState({
testNumber: user_test_total,
number: user_residue_number
})
}
});
}
}
startTest = () => {
const {history, isLogin, toLogin} = this.props;
if(isLogin) {
// history.push('/levelTest/test');
// if(getParam('version')) {
window.location.href = `${API.m}/levelTest/test`;
// }else{
// history.push('/levelTest/test');
// }
}else{
toLogin();
}
}
render() {
let {
testNumber,
number,
prizeListUrl,
} = this.state;
const {isLogin, testSum} = this.props;
return (
<>
<div className="level__test_module">
<div className='start__test' onClick={this.startTest}>
<img className='test-img' src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/test_icon.png" />
<div className="button__text">
<p>点击测试</p>
</div>
</div>
<div className='test__number'>
已有
<span className='number'>
{testNumber || testSum}
</span>
人参加测试
</div>
<div className='prize__rules'>
<div className="prize__title"> 活动奖品 </div>
<div className="prize__list">
{
prizeListUrl.map((item, index) => {
return (
<div className='prize__container' key={index}>
<img src={item.url} />
</div>
)
})
}
</div>
<div className="prize__title"> 活动规则 </div>
<div className="rules__text">
<p>1. 115日至1113日之间每人有一次测试机会,可通过“集福气”活动额外获得2次测试机会;</p>
<p>2. 单次测试时间为一小时,超时自动提交试卷;</p>
<p>3. 试卷内容为Python基础(8道题*3分)、机器学习(12道题*3分)、深度学习(10道题*4分),总分100分;</p>
<p>4. 无固定试卷,参与测试时从试题库中随机抽题组卷;</p>
<p>5. 排行榜实时更新,分数相同则用时短者排名更高,多次测试保留最高分;</p>
<p>6. 如发现某账号有作弊嫌疑,七月在线有权清空账号测试成绩;</p>
<p>7. 活动最终解释权归七月在线所有。</p>
</div>
</div>
</div>
</>
)
}
}
export default listFrame(LevelTest)
.level__test_module {
width: 100%;
// height:580px;
padding-bottom: 20px;
.start__test {
width:174px;
height:33px;
background:linear-gradient(-90deg,rgba(255,140,27,1) 0%,rgba(255,59,5,1) 100%);
border-radius:17px;
margin: 20px auto 8px;
display: flex;
justify-content: center;
align-items: center;
font-size:14px;
font-weight:500;
color:rgba(255,255,255,1);
.button__text {
font-size:14px;
font-weight:500;
color:rgba(255,255,255,1);
display: flex;
flex-direction: row;
justify-content: center;
align-items: baseline;
margin-left: 5px;
span {
font-size:12px;
}
}
.test-img {
width: 14px;
height: 14px;
}
}
.test__number {
font-size:12px;
font-weight:400;
color:rgba(255,255,255,1);
margin: 0 auto;
display: flex;
justify-content: center;
align-items: baseline;
.number {
font-size: 16px;
margin: 0 5px;
}
}
.prize__rules {
width:335px;
// height:461px;
background:rgba(89,112,255,1);
border-radius:5px;
margin: 16px auto;
padding: 15px 10px;
.prize__title {
font-size:14px;
font-weight:400;
color:rgba(255,255,255,1);
text-align: center;
text-align-last: center;
margin-bottom: 10px;
}
.prize__list {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
margin-bottom: 16px;
.prize__container {
width: 100px;
height: 100px;
margin: 0 6px 8px 0;
&:nth-child(3n) {
margin: 0 0 8px 0;
}
}
}
.rules__text {
font-size:12px;
font-weight:400;
color:rgba(240,241,255,1);
line-height:17px;
}
}
}
\ No newline at end of file
import React, { Component } from 'react';
import './index.scss';
function ListFrame(WrappedComponent) {
return class extends Component {
render() {
return (
<div className="list-frame">
<div className="list-frame__content">
<WrappedComponent {...this.props}/>
</div>
</div>
)
}
};
}
export default ListFrame;
.list-frame {
margin: 0 10px;
border: 1px solid #5970FF;
border-radius: 5px;
background-color: #3900C9;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/frame-bg-top.png');
background-repeat: no-repeat;
}
.list-frame__content {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/frame-bg-bottom.png');
background-repeat: no-repeat;
background-position: bottom right;
}
\ No newline at end of file
import React, { Component } from 'react';
import classnames from 'classnames';
import './index.scss';
class ListHeader extends Component {
render() {
const { text, size, styles, id } = this.props;
const cls = size? `list-header--${size}` : '';
return (
<div id={id} className={classnames("list-header", cls)} style={styles}>
<i className="list-header__decorate" data-position="left"></i>
{
text
? <h2 className="list-header__content">{text}</h2>
: this.props.children
}
<i className="list-header__decorate" data-position="right"></i>
</div>
)
}
}
export default ListHeader;
.list-header {
display: flex;
align-items: center;
justify-content: center;
}
.list-header--middle {
.list-header__decorate {
width: 25px;
height: 12px;
}
.list-header__content {
padding: 0 12px;
font-size: 16px;
font-weight: 500;
color: #fff;
}
}
.list-header__decorate {
display: inline-block;
width: 37px;
height: 18px;
background-size: cover;
&[data-position="left"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/list-header-l.png');
}
&[data-position="right"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/list-header-r.png');
}
}
.list-header__content {
margin: 0;
padding: 0 15px;
font-size: 18px;
font-weight: 600;
color: #FFF604;
line-height: 1;
}
\ No newline at end of file
import React, { Component } from 'react'
import './index.scss'
import { Tabs, Toast } from "antd-mobile"
import { getParam, http, SendMessageToApp, browser } from "@/utils"
import { Popup } from "@common/index"
import QRCode from 'qrcode'
import { uniqBy } from 'lodash'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
@connect(state => ({user: state.user}))
class Live extends Component {
popupInstance = null
state = {
tabs: [],
lives: {},
preheatLives: [],
today: '',
isApp: getParam('version'),
QRCodeUrl: '',
}
componentDidMount() {
http.get(`${API.home}/sys/get_live_info`)
.then(res => {
const {data} = res
if (data.code == 200) {
const lives = data.data['data_active'].reduce((accu, current) => {
if (!(current.date in accu)) {
accu[current.date] = [current]
} else {
accu[current.date].push(current)
}
return accu
}, {})
const preheatLives = data.data['data_hot'].reduce((accu, current) => {
if (!(current.date in accu)) {
accu[current.date] = [current]
} else {
accu[current.date].push(current)
}
return accu
}, {})
let tabs, today
if (this.props.isFormal) {
tabs = Object.keys(lives).map(item => ({title: item}))
today = uniqBy(data.data['data_active'], value => value.date).findIndex(item => item['is_today'])
} else {
tabs = Object.keys(preheatLives).map(item => ({title: item}))
today = uniqBy(data.data['data_hot'], value => value.date).findIndex(item => item['is_today'])
}
this.setState({
tabs,
lives,
today,
preheatLives
})
} else {
Toast.info(data.msg, 2, null, false)
}
})
}
toLiveRoom = id => {
const {history, isLogin} = this.props
if (this.state.isApp) {
if (isLogin) {
SendMessageToApp('toLiveRoom', id)
} else {
SendMessageToApp("toLogin")
}
} else {
if (isLogin) {
window.location.href = `${window.location.protocol}//www.julyedu.com/live/m_room/${id}`
} else {
history.push('/passport')
}
}
}
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)
}
}
makeSubscribe = id => {
const {user, history} = this.props
if (user.hasError) {
history.push('/passport/login')
}
http.get(`${API['base-api']}/sys/createLiveQrcode/${id}`)
.then(res => {
const {data} = res
if (data.errno == 200) {
this.setState(() => ({
QRCodeUrl: data.data.url,
}))
QRCode.toDataURL(data.data.url, (err, url) => {
if (!this.popupInstance) {
this.popupInstance = Popup({
title: '扫码关注“七月在线”服务号即可预约',
content: (
<>
<img id={'live-qr-code'} src={url} alt=""/>
{
browser.isAndroidApp ? (
<button className={'save-image'} onClick={this.saveImage}>保存二维码</button>
) : null
}
</>
),
close: () => new Promise(resolve => {
this.popupInstance = null
resolve()
})
})
}
})
} else {
Toast.info(data.msg, 2, null, false)
}
})
}
render() {
const {tabs, lives, preheatLives, today} = this.state
return (
<div id={'live'}>
<div className="title">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/title-decorate-left.png" alt=""/>
<span>大咖直播</span>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/title-decorate-right.png" alt=""/>
</div>
<div className="live-container">
{
today !== '' &&
<Tabs
tabs={tabs}
tabBarBackgroundColor={'transparent'}
tabBarActiveTextColor={'#5600DF'}
tabBarInactiveTextColor={'#FFF604'}
tabBarUnderlineStyle={{display: 'none'}}
initialPage={today}
swipeable={false}
>
{
this.props.isFormal
? tabs.map((item, index) => {
const todayLives = lives[item.title]
return (
<div key={index}>
{
todayLives.map((item, index) => {
return (
<LiveContent item={item} key={index} makeSubscribe={this.makeSubscribe}
toLiveRoom={this.toLiveRoom}/>
)
})
}
</div>
)
})
: tabs.map((item, index) => {
const todayLives = preheatLives[item.title]
return (
<div key={index}>
{
todayLives.map((item, index) => {
return (
<LiveContent item={item} key={index} makeSubscribe={this.makeSubscribe}
toLiveRoom={this.toLiveRoom}/>
)
})
}
</div>
)
})
}
</Tabs>
}
</div>
</div>
)
}
}
function LiveContent({item, makeSubscribe, toLiveRoom}) {
return (
<div className="content">
{
item['is_teacher']
? <div className="tag teacher">讲师分享</div>
: <div className="tag student">学员分享</div>
}
<div className="person-info">
<div className="left">
<img
src={item.avatar}
alt="头像"
className="avatar"/>
</div>
<div className="right">
<div className="name">讲师:{item['teacher']}</div>
<div className="profession">{item['teacher_desc']}</div>
</div>
</div>
<div className="title">{item.title}</div>
<div className="time">直播时间:{item.time}</div>
<div className="outline">
<div className="outline-title">内容大纲:</div>
<ul>
{
item['content'].map((content, index) => {
return <li key={index}>{content}</li>
})
}
</ul>
</div>
{
item['on_live']
? <button className={'on-living'} onClick={() => {
toLiveRoom(item['room_url'])
}}>正在直播</button>
:
item['is_end']
? <button className={'subscribed'}>已结束</button>
: item['is_subscribe']
? <button className={'subscribed'}>已预约</button>
: <button className={'subscribe'}
onClick={makeSubscribe.bind(this, item['live_id'])}>立即预约</button>
}
</div>
)
}
export default withRouter(Live)
#live {
margin-top: 30px;
.title {
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
color: #FFF604;
text-align: center;
margin-bottom: 20px;
span {
margin: 0 15px;
}
img {
width: 37px;
height: 18px;
}
}
.live-container {
width: 355px;
margin: 0 auto;
background: rgba(57, 0, 201, 1);
border: 1px solid rgba(89, 112, 255, 1);
border-radius: 5px;
padding-bottom: 30px;
.content {
position: relative;
width: 325px;
height: 312px;
padding: 26px 30px 0;
margin-top: 50px;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/live-bg.png") no-repeat;
background-size: contain;
color: #333;
text-align: center;
overflow: hidden;
}
.tag {
position: absolute;
right: -75px;
top: 10px;
width: 200px;
height: 36px;
font-size: 11px;
color: #fff;
line-height: 36px;
text-align: center;
transform: rotate(45deg);
&.teacher {
background: linear-gradient(rgba(178, 47, 175, 1) 0%, rgba(246, 64, 152, 1) 100%);
}
&.student {
background: linear-gradient(rgba(10, 72, 245, 1) 0%, rgba(0, 153, 255, 1) 100%);
}
}
.person-info {
display: flex;
}
.name {
color: #3900C9;
font-size: 20px;
text-align: left;
}
.avatar {
width: 55px;
height: 55px;
margin-right: 20px;
border-radius: 50%;
border: 1px solid #5970FF;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
}
.profession {
color: #666;
font-size: 12px;
}
.title {
font-size: 15px;
color: #333;
text-align: left;
margin-bottom: 10px;
display: block;
}
.time {
margin-bottom: 10px;
color: #666;
font-size: 12px;
text-align: left;
}
.outline {
text-align: left;
margin-bottom: 10px;
&-title {
font-size: 14px;
margin-bottom: 6px;
}
li {
font-size: 11px;
color: #666;
}
}
button {
position: absolute;
bottom: 20px;
left: 50%;
margin-left: -67px;
width: 134px;
height: 33px;
border: none;
border-radius: 17px;
outline: none;
font-size: 15px;
color: #fff;
&.subscribe {
padding-left: 25px;
background: linear-gradient(90deg, rgba(255, 140, 27, 1) 0%, rgba(255, 59, 5, 1) 100%);
&::before {
content: '';
display: block;
position: absolute;
left: 25px;
top: 9px;
width: 15px;
height: 15px;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/subscribe-icon.png") no-repeat;
background-size: contain;
}
}
&.subscribed {
background: #CBCED0;
}
&.on-living {
padding-left: 25px;
background: linear-gradient(-90deg, rgba(7, 240, 255, 1) 0%, rgba(0, 153, 255, 1) 100%);
&::before {
content: '';
display: block;
position: absolute;
top: 10px;
left: 25px;
width: 11px;
height: 12px;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/live-play-icon.png") no-repeat;
background-size: contain;
}
}
}
}
.am-tabs {
width: 330px;
margin: 0 auto;
color: #fff;
& .am-tabs-default-bar-tab:nth-last-of-type(2) {
&::after {
display: none;
}
}
.am-tabs-tab-bar-wrap {
height: 33px;
}
.am-tabs-default-bar-tab {
height: auto;
line-height: 1;
&::after {
content: '';
display: block;
position: absolute;
right: 0;
left: unset;
top: 50%;
margin-top: -7px;
width: 1px;
height: 14px;
background: #FFF604;
transform: none;
}
}
.am-tabs-default-bar-tab-active {
background: #FFF604;
border-radius: 0 0 5px 5px;
}
.am-tabs-default-bar-top{
.am-tabs-default-bar-content{
border: 1px solid rgba(255, 246, 4, 1);
border-radius: 0 0 6px 6px;
}
}
}
}
.popup-container {
.title {
color: #525C65;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
img {
width: 120px;
height: 120px;
margin-top: 10px;
}
}
.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;
}
}
import React, { Component } from 'react';
import { http } from '@/utils';
import { Tabs } from 'antd-mobile';
import ListFrame from './../listFrame/index';
import './index.scss';
class LuckDraw extends Component {
constructor(props) {
super(props);
this.state = {
tabs: [],
prizes: []
};
}
componentDidMount() {
this.fetchActivityPrize();
}
fetchActivityPrize = () => {
http.get(`${API.home}/sys/activity/prize_data`).then(res => {
const { code , data: { list = [] } } = res.data;
if(code === 200) {
this.setState({
tabs: list.map(item => {
return {
title: item.date
}
}),
prizes: list
});
}
});
}
render() {
const { tabs, prizes } = this.state;
return (
<div className="luck-draw__container">
<Tabs swipeable={false}
tabs={tabs}
tabBarBackgroundColor="transparent"
tabBarUnderlineStyle={{
display: 'none'
}}
>
{
prizes.map(({ son }, index) => {
return (
<div className="tab__body" key={index}>
{
son.map(val => (
<div key={val.id}>
<h2 className="prize__label">
<i className="prize__label-icon"></i>
<span>{val.time}</span>
</h2>
<div className="prize__content">
{
val.data.map((v, k) => (
<div className="prize__container" key={`${val.id}-${k}`}>
<div className="prize__image">
<img src={v.img} alt="image"/>
</div>
<p className="prize__desc">{v.name}</p>
<p className="prize__desc">*{v.num}</p>
</div>
))
}
</div>
</div>
))
}
</div>
)
})
}
</Tabs>
</div>
)
}
}
export default ListFrame(LuckDraw);
\ No newline at end of file
.luck-draw__container {
.am-tabs {
width: 330px;
margin: 0 auto;
color: #fff;
.am-tabs-tab-bar-wrap {
height: 33px;
border: 1px solid rgba(255, 246, 4, 1);
border-radius: 0 0 6px 6px;
.am-tabs-default-bar {
.am-tabs-default-bar-tab:nth-of-type(3) {
&::after {
display: none;
}
}
.am-tabs-default-bar-tab {
height: auto;
line-height: 1;
&::after {
content: '';
display: block;
position: absolute;
right: 0;
left: unset;
top: 50%;
margin-top: -7px;
width: 1px !important;
height: 14px;
background: #FFF604;
transform: none;
}
}
.am-tabs-default-bar-tab-active {
background: #FFF604;
border-radius: 0 0 6px 6px;
}
}
}
}
}
.tab__body {
padding-bottom: 19px;
}
.prize__label {
display: flex;
align-items: center;
justify-content: center;
width: 125px;
height: 24px;
margin: 20px auto 0;
border-radius: 12px;
font-size: 12px;
font-weight: 500;
color: #fff;
background: linear-gradient(269deg,rgba(7,240,255,1) 0%,rgba(0,153,255,1) 100%);
}
.prize__label-icon {
width: 12px;
height: 14px;
margin-right: 7px;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/icon-clock.png');
background-size: cover;
}
.prize__content {
display: flex;
flex-wrap: nowrap;
padding: 10px 7px 0 0;
overflow-y: auto;
}
.prize__image {
width: 100px;
height: 78px;
margin: 0 3px 10px;
padding: 2px;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/prize-border.png');
background-size: cover;
overflow: hidden;
img {
display: block;
width: 100%;
height: 100%;
}
}
.prize__desc {
width: 100px;
font-size: 12px;
color: #fff;
white-space: nowrap;
text-overflow: ellipsis;
text-align: center;
line-height: 15px;
overflow: hidden;
}
\ No newline at end of file
import React, { Component } from 'react'
import './index.scss'
import {http} from "@/utils"
import ListHeader from './../listHeader';
export default class RankList extends Component {
constructor(props) {
super(props);
this.state = {
rankList: []
}
}
componentDidMount() {
http.get(`${API.home}/sys/ai_test/ranking/10`).then(res => {
let data = res.data.data;
let code = res.data.code;
if(code === 200) {
this.setState({
rankList: data.rankings
})
}
});
}
formart = (time) => {
let date = time * 1000,
hours = 0,
minutes = 0,
seconds = 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);
return `${minutes}'${seconds}"`;
}
render() {
let {rankList} = this.state;
return (
<>
<ListHeader text="测试排行榜" styles={{margin: '20px 0 10px'}} size='middle' />
<div className="sort__rules">
仅显示前10
</div>
<div className="rank__list_module">
<div className="rank__table_head">
<div className="table_head table_head__sort">排名</div>
<div className="table_head table_head__user_info">用户</div>
<div className="table_head table_head__time">用时</div>
<div className="table_head table_head__score">成绩</div>
<div className="table_head table_head__prize">奖品</div>
</div>
<div className="rank__table_body">
{
rankList.map((item, index)=>{
return (
<div className="table__tr" key={index}>
<div className='table__body table_head__sort'>
{
index > 2 ? (index + 1) : (
null
)
}
</div>
<div className='table__body table_head__user_info'>
<img className="user__avatar" src={item.avatar} />
<span className="user__name">{item.user_name}</span>
</div>
<div className='table__body table_head__time'>{this.formart(item.cost_time)}</div>
<div className='table__body table_head__score'>{item.score}</div>
<div className='table__body table_head__prize'>{item.prize}</div>
</div>
)
})
}
</div>
</div>
</>
)
}
}
.rank__list_module {
width:366px;
height:523px;
background:rgba(71,28,230,1);
border-radius:6px;
margin: 16px auto 0;
.rank__table_head {
width: 100%;
height:38px;
background:rgba(89,112,255,1);
border-radius:5px 5px 0px 0px;
display: flex;
justify-content: center;
align-items: center;
.table_head {
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-size: 14px;
font-weight: 400;
}
}
.rank__table_body {
.table__tr {
height: 48px;
display: flex;
justify-content: center;
align-items: center;
&:nth-child(1) {
.table_head__sort {
background: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/gold.png') 50% 50% no-repeat;
background-size: 14px 18px;
}
}
&:nth-child(2) {
.table_head__sort {
background: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/silver.png') 50% 50% no-repeat;
background-size: 14px 18px;
}
}
&:nth-child(3) {
.table_head__sort {
background: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/copper.png') 50% 50% no-repeat;
background-size: 14px 18px;
}
}
&:nth-child(2n) {
background:#3900C9;
}
.table__body {
font-size:12px;
font-weight:400;
color:rgba(255,255,254,1);
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.table_head__user_info {
.user__avatar {
width: 18px;
height: 18px;
border-radius: 50%;
margin-right: 6px;
}
.user__name {
width: 86px;
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.table_head__prize {
display: inline-block;
line-height: 48px;
text-align: start;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.table_head__sort {
width: 50px;
}
.table_head__user_info {
width: 110px;
}
.table_head__time {
width: 58px;
}
.table_head__score {
width: 58px;
}
.table_head__prize {
width: 90px;
}
}
\ No newline at end of file
import React, { Component } from 'react'
import './index.scss'
import { http } from '@/utils';
export default class RecordPopup extends Component {
constructor(props) {
super(props);
this.state = {
recordList: [],
}
}
componentDidMount () {
http.get(`${API.home}/sys/ai_test/get_user_testinfo`).then(res => {
let {code, data: {user_test_record}} = res.data;
if(code === 200) {
this.setState({
recordList: user_test_record
})
}
});
}
render() {
let {recordList} = this.state;
const { handleToHide } = this.props;
return (
<div className='record__mark'>
<div className="gift__record">
<div className="close__button" onClick={handleToHide}>
<i className="icon iconfont iconiconfront-77"></i>
</div>
<p className="mark__title">测试记录</p>
<p className="mark__tip">多次测试保留最高分,可查看最近一次答题记录</p>
<div>
<div className="table__head">
<span className="tr">测试时间</span>
<span className="tr">分数</span>
<span className="tr">操作</span>
</div>
<div className="table__body">
{
recordList.length>0?
recordList.map((item, index) => {
return (<div className="tr__container" key={index}>
<span className="tr">{item.submit_time}</span>
<span className="tr">{item.score}</span>
<span className="tr">
{
index === 0 ? (
<a href={`/levelTest/report?id=${item.id}`}>测试记录</a>
) : (null)
}
</span>
</div>
)
}):
<div className={'notdata'}>暂无测试记录</div>
}
</div>
</div>
</div>
</div>
)
}
}
.record__mark {
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .6);
display: flex;
justify-content: center;
align-items: center;
}
.gift__record {
width: 300px;
background: rgba(255, 255, 255, 1);
border-radius: 5px;
padding: 18px 24px 30px 24px;
position: relative;
span.tr {
display: flex;
justify-content: center;
align-items: center;
display: inline-block;
&:first-child {
width: 120px;
padding-left: 12px;
text-align: start;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&:nth-child(2n) {
width: 55px;
}
&:last-child {
width: 75px;
padding-right: 12px;
text-align: right;
a {
font-size: 12px;
color: #0099ff;
text-decoration: underline;
}
}
}
.table__head {
width: 250px;
height: 34px;
background: rgba(82, 92, 101, 0.1);
border-radius: 1px 1px 0px 0px;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
font-weight: 400;
color: rgba(82, 92, 101, 1);
}
.table__body {
width: 250px;
border: 1px solid rgba(207, 219, 229, 0.4);
border-radius: 0px 0px 1px 1px;
box-sizing: border-box;
overflow: auto;
.tr__container {
display: flex;
justify-content: center;
align-items: center;
height: 34px;
border-bottom: 1px solid rgba(207, 219, 229, 0.4);
&:last-child {
border-bottom: none;
}
p {
color: #525c65;
}
}
}
.notdata{
text-align: center;
color: #999999;
line-height: 35px;
}
.close__button {
width: 24px;
height: 24px;
border-radius: 50%;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -56px;
border: 1px solid #fff;
display: flex;
justify-content: center;
align-items: center;
i {
font-size: 24px;
color: #fff;
}
}
.mark__title {
width: 100%;
font-size: 16px;
line-height: 16px;
font-weight: 500;
color: rgba(82, 92, 101, 1);
margin-bottom: 16px;
text-align: center;
text-align-last: center;
}
.mark__tip {
font-size: 12px;
font-weight: 400;
color: rgba(153, 153, 153, 1);
line-height: 18px;
text-align: start;
text-align-last: start;
margin-bottom: 16px;
}
}
\ No newline at end of file
import React, { Component } from 'react';
import './index.scss';
class BlessingPrehead extends Component {
constructor(props) {
super(props);
this.state = {
rules: [
'• 抽奖的次数可通过积福气获得,福气值越高,抽奖的次数越多;',
'• 本次抽奖形式为开奖制,下一时段开启抽奖前会公布上一次中奖结果及名单,可关注“七月在线”服务号及时获取中奖结果,提醒参与下次抽奖;',
'• 每个时段仅可使用一次抽奖机会,每日抽奖次数限当日用,抽奖次数不累加至次日;',
'• 中奖后请及时填写邮寄信息,不填写视为主动放弃奖品;',
'• 解释权归北京七月在线所有。',
]
}
}
render() {
const { rules } = this.state;
const { handleToHide } = this.props;
return (
<div className="rule-popup__container">
<div className="rule-popup">
<h2 className="rule-popup__title">活动规则</h2>
<ul className="rule-popup__list">
{rules.map((item, index) => (
<li className="rule-popup__item" key={index}>{item}</li>
))}
</ul>
</div>
<i className="iconfont iconiconfront-2" onClick={handleToHide}></i>
</div>
);
}
}
export default BlessingPrehead;
\ No newline at end of file
.rule-popup__container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
z-index: 999;
.iconfont {
margin: 16px 0 0;
font-size: 24px;
color: #fff;
cursor: pointer;
}
}
.rule-popup {
width: 300px;
height: 323px;
padding: 20px 0 0;
border-radius: 10px;
box-sizing: border-box;
text-align: center;
background-color: #fff;
}
.rule-popup__title {
margin: 0 0 15px;
font-size: 16px;
font-weight: 500;
color: #525C65;
text-align: center;
line-height: 1;
}
.rule-popup__list {
padding: 0 20px;
}
.rule-popup__item {
font-size: 14px;
color: rgba(82, 92, 101, .9);
text-align: left;
line-height: 21px;
}
\ No newline at end of file
import React, { Component } from 'react';
import { browser } from '@/utils';
import './index.scss'
export default class SharePopup extends Component {
render() {
return (
<div className="share__container" onClick={() => {
if(this.props.isClose) {
this.props.toClose();
}
}}>
{
browser.isWeixin &&
<div className="share__row">
<img src='https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/throw_icon.png' />
</div>
}
<div className="share__content">
<p className="share__text">分享活动页到朋友圈、qq、微博分别</p>
<div className='share__rule'>
<img className={'share__add2'} src='https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/add2.png' />
<span>(每个平台每天一次)</span>
</div>
</div>
</div>
)
}
}
.share__container {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, .6);
z-index: 999;
.share__row {
width: 60px;
height: 44px;
position: absolute;
right: 16px;
top: 10px;
}
.share__content {
width:290px;
height:71px;
background:rgba(255,255,255,1);
border-radius:10px;
position: absolute;
top: 70px;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.share__text {
font-size:16px;
font-weight:400;
color:rgba(82,92,101,1);
}
.share__rule {
height: 18px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 12px;
color: #525C65;
}
.share__add2{
width: 95px;
}
}
}
\ No newline at end of file
import React, {Component} from 'react'
import {SendMessageToApp,wxShare} from '@/utils'
import {setCurrentUser, startFetchUser} from "@/store/userAction"
import {Button, Toast, WhiteSpace} from 'antd-mobile'
import cookie from 'js-cookie'
import {addDays} from "date-fns"
import {compose} from "redux";
import {connect} from "react-redux";
class ToAppDemo extends Component {
state = {
userInfoList: [],
}
componentDidMount() {
this.getData()
// 获取App登录信息
window['loginInfo'] = result => {
this.loginInfo(result)
}
}
getData = () => {
Toast.info('获取福气值', 2)
}
// 获取app登录数据
loginInfo = (result) => {
this.setState({
userInfoList: result
})
if (this.state.userInfoList.length !== 0) {
this.props.startFetchUser()
this.appLogin()
}
}
// 保存cookie
appLogin = () => {
let expires = addDays(new Date(), 90)
this.state.userInfoList.map((item, index) => {
Toast.info(item.version, 3)
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'});
});
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
}
testShare = () => {
wxShare({
title: 'AI充电节,积福气享1折秒课,超10万元奖品来就送!!',
desc: '把这门超5万人报名的【Python基础入门 升级版】课程送给你,附200元红包,请笑纳!--七月在线',
link: encodeURI(location.href),
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/index-share-img.png',
})
}
// 跳转App登录
toLogin = () => {
SendMessageToApp("toLogin");
}
// 立即付定金
earnestMoney = (courseId) => {
SendMessageToApp("earnestMoney", courseId);
}
// 去课程详情页
toCourse = (courseId, type) => {
let data = {
courseId: courseId,
type: type // 正常跳课程详情页type:0,积福气浏览课程详情页-没有浏览过type:1 已浏览过type:2
}
SendMessageToApp("toCourse", data);
}
// 人工咨询
toQQ = () => {
SendMessageToApp("toQQ", 'https://q.url.cn/AB8aue?_type=wpa&qidian=true')
}
// 直播间
toLiveRoom = (toLiveRoom) => {
SendMessageToApp("toLiveRoom", toLiveRoom)
}
// QQ分享
QQshare = () => {
// 内容需要和产品确认
let data = {
title: 'AI充电节,积福气享1折秒课,超10万元奖品来就送!!',
desc: '把这门超5万人报名的【Python基础入门 升级版】课程送给你,附200元红包,请笑纳!--七月在线',
link: 'https://m.julyedu.com/blessingPreheat',
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/index-share-img.png',
}
SendMessageToApp("QQshare", data)
}
// 微信分享
WXshare = () => {
// 内容需要和产品确认
let data = {
title: 'AI充电节,积福气享1折秒课,超10万元奖品来就送!!',
desc: '把这门超5万人报名的【Python基础入门 升级版】课程送给你,附200元红包,请笑纳!--七月在线',
link: 'https://m.julyedu.com/blessingPreheat',
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/index-share-img.png',
}
SendMessageToApp("WXshare", data)
}
// 邀请好友注册
toShare = () => {
let data = {
title: 'AI充电节,积福气享1折秒课,超10万元奖品来就送!!',
desc: '把这门超5万人报名的【Python基础入门 升级版】课程送给你,附200元红包,请笑纳!--七月在线',
link: 'https://m.julyedu.com/blessingPreheat',
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/index-share-img.png',
}
SendMessageToApp("toShare", data)
}
render() {
return (
<div>
<Button type={'primary'} onClick={() => this.testShare()}>测试分享</Button><WhiteSpace/>
<p>登录</p>
<Button type={'primary'} onClick={() => this.toLogin()}>App登录</Button><WhiteSpace/>
<p>去课程详情页</p>
<Button type={'primary'} onClick={() => this.toCourse(165, 0)}>课程详情页</Button><WhiteSpace/>
<p>积福气</p>
<Button type={'primary'} onClick={() => this.toCourse(165, 1)}>浏览课程详情页</Button><WhiteSpace/>
<Button type={'primary'} onClick={() => this.QQshare()}>分享(QQ</Button><WhiteSpace/>
<Button type={'primary'} onClick={() => this.WXshare()}>分享(微信)</Button><WhiteSpace/>
<Button type={'primary'} onClick={() => this.toShare()}>邀请好友注册</Button><WhiteSpace/>
<p>定金相关</p>
<Button type={'primary'} onClick={() => this.earnestMoney(165)}>立即付定金</Button><WhiteSpace/>
<Button type={'primary'} onClick={() => this.toCourse(165, 0)}>去学习(跳课程详情页)</Button><WhiteSpace/>
<p>精品特惠</p>
<Button type={'primary'} onClick={() => this.toQQ()}>立抢超低团购价(跳人工咨询)</Button><WhiteSpace/>
<Button type={'primary'} onClick={() => this.toCourse(165, 0)}>开始使用(跳课程详情页)</Button><WhiteSpace/>
<Button type={'primary'} onClick={() => this.toCourse(165, 0)}>一分钱开团(跳课程详情页)</Button><WhiteSpace/>
<p>大咖直播</p>
<Button type={'primary'} onClick={() => this.toLiveRoom(100)}>正在直播</Button><WhiteSpace/>
</div>
)
}
}
export default compose(
connect(
state => ({user: state.user}),
{setCurrentUser, startFetchUser}
)
)(ToAppDemo)
\ No newline at end of file
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { http } from "@/utils"
import { Popup } from '@/common'
import AddressPopup from './../blessingPreheat/addressPopup/index'
import './index.scss'
@connect(({user}) => (
{
uid: user.data.uid || ''
}
))
class BlessingRank extends Component {
popupInstance = null
constructor(props) {
super(props)
this.state = {
rankList: [],
rules: [
'1、排行榜名次以2019年11月13日24点七月在线公布的排行榜为准,榜单确认后,得奖小伙伴请及时填写邮寄信息,7个自然日内不填写,视为主动放弃奖品;',
'2、福气值只在本活动期间享受抽奖、提高中奖概率、购课优化、增加AI水平测试等福利;',
'3、如有发现恶意刷榜,刷虚假数据等行为将取消其领奖资格;',
'4、本活动解释权归北京七月在线科技有限公司所有。',
],
}
}
componentDidMount() {
this.fetchRankData()
}
fetchRankData = () => {
http.get(`${API.home}/sys/blessing/ranking`).then(res => {
const {code, data} = res.data
if (code === 200) {
this.setState({
rankList: data,
})
}
})
}
handleToSwitch = (bool) => {
const {history, uid} = this.props
if (bool && !uid) {
history.push('/passport')
} else {
if (bool && !this.popupInstance) {
this.popupInstance = Popup({
title: '收货信息',
content: <AddressPopup handleToHide={() => this.handleToSwitch(false)}/>
})
} else {
this.popupInstance.close()
this.popupInstance = null
}
}
}
formatString = (str, len) => {
return str.length > len ? `${str.substr(0, len)}...` : str
}
render() {
const {rankList, rules} = this.state
return (
<>
<div className="rank__banner"></div>
<div className="rank__body">
<button className="rank__address" onClick={() => this.handleToSwitch(true)}>填写收货地址></button>
<div className="rank__table">
<dl className="rank__table-header">
<dd className="rank__table-column">排名</dd>
<dd className="rank__table-column">用户</dd>
<dd className="rank__table-column">成绩</dd>
<dd className="rank__table-column">奖品</dd>
</dl>
{
rankList.map((item, index) => {
return (
<dl className="rank__table-body" key={index}>
<dd className="rank__table-column">
{
index < 3
? (
<i className="rank__table-num" data-num={index + 1}></i>
)
: index + 1
}
</dd>
<dd className="rank__table-column">
<div className="rank__table-user">
<i className="rank__table-portrait" style={{backgroundImage: `url(${item.head_image})`}}></i>
<span>{this.formatString(item.user_name, 5)}</span>
</div>
</dd>
<dd className="rank__table-column">{item.blessing_value}</dd>
<dd className="rank__table-column">{this.formatString(item.prize_name, 7)}</dd>
</dl>
)
})
}
</div>
<div className="rank__rule">
<h2 className="rank__rule-title">活动规则</h2>
{
rules.map((item, index) => (
<p className="rank__rule-desc" key={index}>{item}</p>
))
}
</div>
</div>
</>
)
}
}
export default BlessingRank
.rank__banner {
height: 168px;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/rank-banner.png');
background-size: cover;
}
.rank__body {
padding: 20px 5px 39px;
background-color: #5327FA;
}
.rank__address {
display: block;
width: 133px;
height: 26px;
margin: 0 auto 10px;
padding: 0;
border: 1px solid #FFF604;
border-radius: 13px;
box-sizing: border-box;
font-size: 13px;
color: #FFF604;
line-height: 26px;
background-color: transparent;
outline: none;
cursor: pointer;
}
.rank__table {
display: table;
width: 100%;
margin: 0 0 20px;
border-radius: 5px;
overflow: hidden;
}
.rank__table-header {
display: table-row;
height: 38px;
border-radius: 5px 5px 0px 0px;
background-color: #5970FF;
}
.rank__table-body {
display: table-row;
height: 38px;
background-color: #471CE6;
&:nth-child(odd) {
background-color: #3900C9;
}
}
.rank__table-column {
display: table-cell;
font-size: 14px;
color: #fff;
text-align: center;
vertical-align: middle;
&:nth-child(1) {
width: 15%;
}
&:nth-child(2) {
width: 30%;
}
&:nth-child(3) {
width: 20%;
}
&:nth-child(4) {
width: 35%;
}
}
.rank__table-num {
display: inline-block;
width: 14px;
height: 16px;
background-size: cover;
&[data-num="1"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/-s-diyiming.png');
}
&[data-num="2"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/-s-dierming.png');
}
&[data-num="3"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/-s-disanming.png');
}
}
.rank__table-user {
display: inline-flex;
align-items: center;
justify-content: center;
}
.rank__table-portrait {
display: inline-block;
width: 18px;
height: 18px;
margin-right: 5px;
border-radius: 50%;
background-size: cover;
}
.rank__rule {
margin: 0 5px;
padding: 20px 20px 48px;
border-radius: 5px;
background-color: #5970FF;
}
.rank__rule-title {
position: relative;
width: 103px;
margin: 0 auto 15px;
font-size: 14px;
font-weight: 400;
color: #fff;
text-align: center;
line-height: 1;
&::after {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 10px;
height: 1px;
background-color: #fff;
}
&::before {
content: '';
position: absolute;
top: 50%;
right: 0;
width: 10px;
height: 1px;
background-color: #fff;
}
}
.rank__rule-desc {
font-size: 12px;
color: #F0F1FF;
line-height: 18px;
}
\ No newline at end of file
$bg_type1: #FE6161;
$bg_type2: #E0B97B;
$bg_voucher: #FE6161;
$bg_free: #E0B97B;
$bg_expand: #8361FE;
.coupon {
position: relative;
margin-bottom: 15px;
......@@ -27,13 +28,14 @@ $bg_type2: #E0B97B;
}
}
.course-title{
.course-title {
width: 68.37%;
margin: 0 auto 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: $font_16;
text-align: center;
}
.expire {
......@@ -43,14 +45,18 @@ $bg_type2: #E0B97B;
}
&.coupon-type1 {
background: $bg_type1;
background: $bg_voucher;
}
&.coupon-type2 {
background: $E0B97B;
}
&.invalid{
&.coupon-type4 {
background: $bg_expand;
}
&.invalid {
background: $color_999;
}
......@@ -87,6 +93,44 @@ $bg_type2: #E0B97B;
transform: translateY(50%);
}
}
.progress-container {
width: 299px;
margin: 0 auto;
.denomination {
font-size: 15px;
line-height: 1.3em;
color: #F8E71C;
span{
transform: scale(0.9);
}
}
.progress-bar-container {
position: relative;
height: 7px;
background: #5C2FFF;
border-radius: 4px;
overflow: hidden;
margin-bottom: 6px;
.progress-bar {
position: absolute;
left: 0;
top: 0;
height: 100%;
background: #F8E71C;
border-radius: 4px;
}
}
.money {
display: flex;
justify-content: space-between;
}
}
}
.coupon-des {
......@@ -117,5 +161,15 @@ $bg_type2: #E0B97B;
background: transparent;
-webkit-appearance: none;
}
.stop-expanding {
padding: 3px 8px;
border: 1px solid #FF3131;
border-radius: 10px;
-webkit-appearance: none;
background: transparent;
color: #FF3131;
font-size: 10px;
}
}
}
\ No newline at end of file
}
import React, { PureComponent } from 'react'
import './coupon.scss'
import classnames from 'classnames'
import { http } from "@/utils"
import showAlert from '@common/deposit/end-expansion-alert'
import { Toast } from 'antd-mobile'
import { withRouter } from "react-router-dom"
class Coupon extends PureComponent {
pick = () => {
let {useCoupon, invalid} = this.props
!invalid && useCoupon && useCoupon(this.props.id)
VOUCHER = 1 //代金券
FREE = 2 //免单券
EXPAND = 4 //膨胀全
}
GoToUse = () => {
this.props.useCoupon(this.props.id)
pick = (e) => {
let {useCoupon, invalid, start_amount, id, location, history, code} = this.props
const {state} = location
if(state && state.from && state.from === '/my' && typeof start_amount !== 'undefined'){
history.push(`/expand/index?deposit_code=${code}`)
return
}
ExchangeCourse = (e) => {
this.props.toExchangeCourse(e,this.props.code)
if (start_amount) {
this.stopExpanding(id, e)
} else {
!invalid && useCoupon && useCoupon(this.props.id)
}
render() {
let {
ctype,
amount,
format_expire_time,
limit_course,
invalid,
course_title,
id,
code,
selectedCouponId,
showUseButton
} = this.props
return (
<li className='coupon' onClick={this.pick}>
<div className={classnames('coupon-info', invalid ? 'invalid' : `coupon-type${ctype}`)}>
<p className='type'>{ctype === 1 ? '代金券' : '课程券'}</p>
{
ctype === 1 ? <p className='denomination'>{amount} <span></span></p>
: <p className='course-title'>{course_title}</p>
}
<p className='expire'>有效期至:{format_expire_time}</p>
{
selectedCouponId === id &&
<i className={classnames('iconfont icondanseshixintubiao-5', {
check: !invalid
})}
/>
}
<ul>
{
new Array(19).fill('a').map((item, index) => {
return <li key={index}/>
})
}
</ul>
</div>
<div className="coupon-des">
<span className='limit'>{
limit_course === 0 ? '可用于大于代金券金额的课程' : `仅适用于《${course_title}》`
}</span>
{
showUseButton && ctype == 1 &&
<button
className='use'
onClick={this.GoToUse}
>立即使用
</button>
}
{
showUseButton && ctype == 2 &&
<button
className='use'
onClick={(e)=>this.ExchangeCourse(e)}
>立即兑换
</button>
}
}
GoToUse = () => {
this.props.useCoupon(this.props.id)
}
ExchangeCourse = (e) => {
this.props.toExchangeCourse(e, this.props.code)
}
stopExpanding = (id, e) => {
const {amount, limit_amount} = this.props
e.stopPropagation()
showAlert({
amount,
limit_amount,
onConfirm: () => {
http.post(`${API.home}/m/end_expansion`, {
id
})
.then(res => {
const {data} = res
if (data.code == 200) {
this.props.endExpansion(id, data.data.coupon_id)
} else {
Toast.info(data.msg)
}
})
}
})
}
render() {
let {
ctype,
amount,
course_title,
showUseButton,
id,
format_expire_time,
start_amount,
limit_amount
} = this.props
let top, bottom
switch (ctype) {
case this.VOUCHER:
top = (
<>
<p className='denomination'>{amount} <span></span></p>
<p className='expire'>有效期至:{format_expire_time}</p>
</>
)
bottom = (
<>
<span className={'limit'}>可用于大于代金券金额的课程</span>
{
showUseButton && ctype == this.VOUCHER &&
<button
className='use'
onClick={this.GoToUse}
>立即使用
</button>
}
</>
)
break
case this.FREE:
top = (
<>
<p className='course-title'>{course_title}</p>
<p className='expire'>有效期至:{format_expire_time}</p>
</>
)
bottom = (
<>
<span className={'limit'}>{`仅适用于《${course_title}》`}</span>
{
showUseButton && ctype == this.FREE &&
<button
className='use'
onClick={(e) => this.ExchangeCourse(e)}
>立即兑换
</button>
}
</>
)
break
case this.EXPAND:
if (!start_amount) {
top = (
<>
<p className='denomination'>{amount} <span></span></p>
<p className='expire'>有效期至:{format_expire_time}</p>
</>
)
} else {
top = (
<>
<div className="progress-container">
<p className='denomination'>{amount} <span></span></p>
<div className={'progress-bar-container'}>
<span className={'progress-bar'}
style={{width: `${Math.round((amount - start_amount) / limit_amount * 100)}%`}}
></span>
</div>
<div className={'money'}>
<span>{start_amount}</span>
<span>{limit_amount}</span>
</div>
</li>
);
</div>
</>
)
}
bottom = (
<>
<span className={'limit'}>全场通用</span>
{
start_amount
&& <button className='stop-expanding'
onClick={this.stopExpanding.bind(this, id)}>立即结束膨胀</button>
}
</>
)
break
}
return (
<BaseCoupon
{...this.props}
top={top}
VOUCHER={this.VOUCHER}
FREE={this.FREE}
EXPAND={this.EXPAND}
pick={this.pick}
bottom={bottom}
/>
)
}
}
function BaseCoupon(
{
pick,
ctype,
invalid,
top,
VOUCHER,
FREE,
EXPAND,
selectedCouponId,
id,
bottom
}) {
let couponTypes = {
[VOUCHER]: '代金券',
[FREE]: '课程券',
[EXPAND]: '膨胀券'
}
return (
<li className='coupon' onClick={pick}>
<div className={classnames('coupon-info', invalid ? 'invalid' : `coupon-type${ctype}`)}>
<p className='type'>{couponTypes[ctype]}</p>
{top}
{
selectedCouponId === id &&
<i className={classnames('iconfont icondanseshixintubiao-5', {
check: !invalid
})}
/>
}
<ul>
{
new Array(19).fill('a').map((item, index) => {
return <li key={index}/>
})
}
</ul>
</div>
<div className="coupon-des">
{bottom}
</div>
</li>
)
}
export default Coupon
\ No newline at end of file
export default withRouter(Coupon)
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