Commit 2fdcc747 by xuzhenghua

lujing

parents d2ea7aaf 6915df36
......@@ -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;
}
}
}
......@@ -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 {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 {
Toast.info('领取成功,你可前往七月在线官网/APP进行查看', 2);
localStorage.setItem('lingqu', 1);
}
}
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: 'https://m.julyedu.com/blessingPreheat',
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: 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: 30px;
font-size: 11px;
color: #fff;
text-align: center;
line-height: 30px;
&.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 { http, SendMessageToApp } from "@/utils";
import { Link } from 'react-router-dom';
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="course-popup__item"
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: 24px;
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__name {
width: 200px;
font-size: 12px;
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;
border: 1px solid rgba(255, 246, 4, 1);
border-radius: 0 0 6px 6px;
}
.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 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;
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.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>
</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;
height: 250px;
background: rgba(255, 255, 255, 1);
border-radius: 5px;
padding: 18px 24px 0 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;
height: 102px;
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;
}
}
}
.close__button {
width: 32px;
height: 32px;
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: 32px;
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 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;
}
}
}
\ No newline at end of file
import React, {Component} from 'react'
import {SendMessageToApp} from '@/utils'
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 {
......@@ -29,6 +32,7 @@ class ToAppDemo extends Component {
userInfoList: result
})
if (this.state.userInfoList.length !== 0) {
this.props.startFetchUser()
this.appLogin()
}
}
......@@ -43,6 +47,34 @@ class ToAppDemo extends Component {
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',
})
}
......@@ -76,10 +108,10 @@ class ToAppDemo extends Component {
QQshare = () => {
// 内容需要和产品确认
let data = {
title: '11.11-11.13 AI充电节,预热来袭!重磅好课1折秒,超10万元奖品来就送-七月在线', // 标题
desc: '11.11-11.13 AI充电节,预热来袭!重磅好课1折秒,超10万元奖品来就送-七月在线', // 描述
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/shareimg.png', // 图片地址
link: 'https://m.julyedu.com/blessingPreheat' // url
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)
}
......@@ -87,10 +119,10 @@ class ToAppDemo extends Component {
WXshare = () => {
// 内容需要和产品确认
let data = {
title: '11.11-11.13 AI充电节,预热来袭!重磅好课1折秒,超10万元奖品来就送-七月在线', // 标题
desc: '11.11-11.13 AI充电节,预热来袭!重磅好课1折秒,超10万元奖品来就送-七月在线', // 描述
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/shareimg.png', // 图片地址
link: 'https://m.julyedu.com/blessingPreheat' // url
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)
}
......@@ -98,10 +130,10 @@ class ToAppDemo extends Component {
// 邀请好友注册
toShare = () => {
let data = {
title: '11.11-11.13 AI充电节,预热来袭!重磅好课1折秒,超10万元奖品来就送-七月在线', // 标题
desc: '11.11-11.13 AI充电节,预热来袭!重磅好课1折秒,超10万元奖品来就送-七月在线', // 描述
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/shareimg.png', // 图片地址
link: 'https://m.julyedu.com/blessingPreheat' // url
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)
}
......@@ -109,6 +141,7 @@ class ToAppDemo extends Component {
render() {
return (
<div>
<Button type={'primary'} onClick={() => this.testShare()}>测试分享</Button><WhiteSpace/>
<p>登录</p>
<Button type={'primary'} onClick={() => this.toLogin()}>App登录</Button><WhiteSpace/>
<p>去课程详情页</p>
......@@ -132,4 +165,10 @@ class ToAppDemo extends Component {
}
}
export default ToAppDemo
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
......@@ -23,7 +23,7 @@ class Deposit extends Component {
<div className="expand-bgimg">
<img
className="four-year"
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/4year.png"
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/dj-1111.png"
alt=''
/>
<span className="dingjin">定金{info.deposit_amount}元,可抵扣{info.deduction_amount}</span>
......
......@@ -13,7 +13,7 @@
width: 100%;
height: 70px;
background-size: cover;
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/detail-expand-bg.png");
background-image: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/detail-expand-bg.png");
.four-year {
width: 104px;
......
......@@ -21,6 +21,7 @@ class ToGroup extends Component {
number: 0, // 差几人成团
isBuy: false,
modal: false,
pddOrderId:''
}
}
......@@ -57,22 +58,26 @@ class ToGroup extends Component {
person_num: res.data.data.person_num,
course_list: res.data.data.course_list,
number: res.data.data.number,
pddOrderId: res.data.data.pdd_order_id,
countdown: '',
isBuy: res.data.data.is_buy
});
if (res.data.data.is_success === 0) {
let date = res.data.data.end_time * 1000,
day = 0,
hours = 0,
minutes = 0,
seconds = 0;
setInterval(() => {
date -= 1000
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);
day = `${parseInt(date / (3600000 * 24))}`.padStart(2, 0);
hours = `${parseInt((date- day * 3600000 * 24)/3600000)}`.padStart(2, 0);
minutes = `${parseInt((date - day * 3600000 * 24 - hours * 3600000) / 60000)}`.padStart(2, 0);
seconds = `${parseInt((date - day * 3600000 * 24 - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
this.setState({
countdown: `${hours}:${minutes}:${seconds}`
// countdown: `${day}:${hours}:${minutes}:${seconds}`
countdown: `${day}${hours}${minutes}分`
});
}, 1000)
}
......@@ -98,7 +103,8 @@ class ToGroup extends Component {
history.push(
`/order?id=${data.course_id}`,
{
group: 1
group: 1,
pdd_order_id:this.state.pddOrderId
}
)
} else {
......
......@@ -48,7 +48,9 @@ class Detail extends Component {
nowPrice: 0,
laterPrice: 0,
isPdd: 0, // 是否是拼团课程 控制首次单集购买后的 全集购买 接口: 拼团课程走拼团接口,否则直接走购买接口
isRedPacket: true
isRedPacket: true,
countDownTime: '20s',
}
}
......@@ -73,6 +75,51 @@ class Detail extends Component {
isRedPacket: true
});
}
if(getParam('ac') && Number(getParam('ac')) === 11) {
this.getBorwerCourse();
}
}
getBorwerCourse = () => {
http.get(`${API.home}/sys/user/blessing`, {type: 4, course_id: getParam('id')}).then(res => {
let {code, data: {today_browsed_courses}} = res.data;
if(code === 200) {
let currentCourseId = getParam('id');
if(today_browsed_courses.includes(Number(currentCourseId))) {
this.setState({
countDownTime: '任务完成'
});
}else{
this.startActivity();
}
}
})
}
startActivity = () => {
let _this = this;
let countDownInterval = setInterval(function() {
let countDown = parseInt(_this.state.countDownTime);
countDown--;
if(countDown > 0) {
_this.setState({
countDownTime: countDown + 's'
});
} else if(countDown === 0) {
clearInterval(countDownInterval);
countDownInterval = null;
http.post(`${API.home}/sys/add/blessing`, {type: 4, course_id: getParam('id')}).then(res => {
let {code} = res.data;
if(code === 200) {
_this.setState({
countDownTime: '任务完成'
});
}
})
}
}, 1000)
}
// 判断时候未红包课程
......@@ -298,16 +345,19 @@ class Detail extends Component {
if (course_info.group_status === 3 || course_info.group_status === 4) {
let endTime = course_info.pdd_group_info.groupon_member.end_time;
let date = endTime * 1000,
day = 0,
hours = 0,
minutes = 0,
seconds = 0;
setInterval(() => {
date -= 1000
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);
day = `${parseInt(date / (3600000 * 24))}`.padStart(2, 0);
hours = `${parseInt((date- day * 3600000 * 24)/3600000)}`.padStart(2, 0);
minutes = `${parseInt((date - day * 3600000 * 24 - hours * 3600000) / 60000)}`.padStart(2, 0);
seconds = `${parseInt((date - day * 3600000 * 24 - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
this.setState({
countdown: `${hours}:${minutes}:${seconds}`
// countdown: `${day}:${hours}:${minutes}:${seconds}`
countdown: `${day}${hours}${minutes}分`
});
}, 1000)
}
......@@ -443,7 +493,7 @@ class Detail extends Component {
}
render() {
const {course: {course_info = {}}, barInfo, singleBox, singleType, isRedPacket} = this.state;
const {course: {course_info = {}}, barInfo, singleBox, singleType, isRedPacket, countDownTime} = this.state;
let courseInfo = '',
service = '',
......@@ -468,8 +518,17 @@ class Detail extends Component {
if (getParam('dist_code')) {
href = '/'
}
let isCent = course_info.pdd_group_info && course_info.pdd_group_info.price != '0.01';
return (
<div>
{
Number(getParam('ac')) === 11 ? (
<div className='activity__blessing'>
<img src='https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/count_donw.png' />
<span className='count__down__time'>{`${countDownTime}`}</span>
</div>
) : (null)
}
<div className='detail-box'>
<HeaderBar
title='课程详情'
......@@ -641,17 +700,19 @@ class Detail extends Component {
* 拼团
* is_aist: 是否AI特训营
* group_status: 团状态,3:课程有小团 用户没参加小团;4:用户参加了小团
* 拼团价格为1分钱时,不允许参团
*/
}
{
!course_info.is_aist && (course_info.group_status === 3 || course_info.group_status === 4) &&
<Group
courseInfo={course_info}
history={this.props.history}
countdown={countdown}
invitedFriends={this.invitedFriends}
/>
}
{/*双十一期间不需要显示 不要删除*/}
{/*{*/}
{/*isCent && !course_info.is_aist && (course_info.group_status === 3 || course_info.group_status === 4) &&*/}
{/*<Group*/}
{/*courseInfo={course_info}*/}
{/*history={this.props.history}*/}
{/*countdown={countdown}*/}
{/*invitedFriends={this.invitedFriends}*/}
{/*/>*/}
{/*}*/}
{/*
* 砍价
......
......@@ -230,4 +230,27 @@
font-weight: 500;
width: 215px;
}
}
.activity__blessing {
position: fixed;
bottom: 170px;
right: 4px;
width: 76px;
height: 64px;
z-index: 999;
.count__down__time {
width: 62px;
height: 20px;
font-size: 12px;
font-weight: 600;
color:rgba(36,0,119,1);
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 4px;
left: 8px;
}
}
\ No newline at end of file
......@@ -39,6 +39,9 @@
}
.dec {
margin-top: 15px;
a{
word-break:break-all;
}
}
}
......
import React, {Component} from 'react'
import './share.scss'
import {http, getParam, browser, wxShare} from '@/utils'
import {http, getParam, browser, wxShare,is_weixin} from '@/utils'
import {Toast} from 'antd-mobile'
import {connect} from "react-redux";
import {Link} from "react-router-dom";
......@@ -21,13 +21,14 @@ class ExpandShare extends Component {
componentDidMount() {
this.getListorData()
this.getCourseList()
wxShare({
title: '七月在线4岁啦,80元红包等你来拿!',
desc: '重磅好课1元购,大奖、红包轰趴7天7夜',
link: window.location.href,
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/717/shareimg.png',
})
if(is_weixin()) {
wxShare({
title: 'AI充电节,预热来袭!80元红包送给你,手要快!',
desc: '积福气享1折秒课,超10万元奖品来就送--七月在线',
link: window.location.href,
imgUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/dj-share-img.png',
})
}
}
// 获取膨胀券相关
......@@ -225,7 +226,7 @@ class ExpandShare extends Component {
return (
<div className="expand-box">
<div className="banner">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_717/m/zl-banner.png" alt=""/>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/dj-banner.png" alt=""/>
<span onClick={() => this.showRule()}/>
</div>
<div className="all-contnet">
......
......@@ -193,7 +193,7 @@ function PayInfo(props) {
</p>
<p>
<span className='payable'>已优惠:</span>
<span className='price'>¥{props.item.deposit_cut}</span>
<span className='price'>¥{props.item.discount}</span>
</p>
</div>
......
......@@ -176,10 +176,10 @@ class FinalDepositOrder extends Component {
//创建订单
createOrder = () => {
const {selectedCourses, salePrice, useBalance, user_account} = this.state
const {selectedCourses, salePrice, useBalance, user_account, appliedMoneyOffRule} = this.state
return http.post(`${API["base-api"]}/m/deposit/final/create`, {
course_ids: selectedCourses.map(item => item.course_id),
cut_amount: 0,
cut_amount: appliedMoneyOffRule.cut_amount || 0,
pay_amount: salePrice,
is_deduction: useBalance ? 1 : 0,
deduction_amount: useBalance ? this.getBalanceOffset() : 0,
......@@ -400,8 +400,9 @@ class FinalDepositOrder extends Component {
getBalanceOffset = () => {
let originalTotalPrice = this.getOriginTotalPrice()
let offset = parseFloat(this.state.user_account) - parseFloat(originalTotalPrice)
offset = offset >= 0 ? originalTotalPrice : this.state.user_account
let currentPrice = this.moneyOff(originalTotalPrice)
let offset = parseFloat(this.state.user_account) - parseFloat(currentPrice)
offset = offset >= 0 ? currentPrice : this.state.user_account
return offset
}
......@@ -421,7 +422,7 @@ class FinalDepositOrder extends Component {
return (
<div className='deposit-pay-order'>
<HeaderBar title='课程报名' arrow={true}></HeaderBar>
<WhiteSpace size='sm'></WhiteSpace>
<WhiteSpace size='sm' />
{/*<div className='order-number'>
<WingBlank>
<Flex justify='between' align='center' style={{height: '44px'}}>
......@@ -430,38 +431,41 @@ class FinalDepositOrder extends Component {
</Flex>
</WingBlank>
</div>*/}
<WhiteSpace size='md'></WhiteSpace>
<WhiteSpace size='md' />
<div className={'order-list'}>
<OrderList courses={categoryList}
toggleSelectedCourse={this.toggleSelectedCourse}
<OrderList
courses={categoryList}
toggleSelectedCourse={this.toggleSelectedCourse}
/>
</div>
<div className="order-balance">
<List>
<Item
className="order-prefer-text"
>
<Item className="order-prefer-text">
<Flex justify='between'>
<Flex align='center'>
<span>余额抵扣</span>
<span className="order-balanceprice"> (余额: <i
className="order-money">{`${user_account}元`}</i>)</span>
<span className="order-balanceprice">
(余额:
<i className="order-money">{`${user_account}元`}</i>
)
</span>
<i className="iconfont iconiconfront-22 question-mark" onClick={this.showInfo}></i>
</Flex>
<Flex>
{
useBalance ? (
<>
<span style={{
color: '#FF2121',
fontSize: '15px',
marginRight: "6px"
}}>{`-¥${offset}`}</span>
<i className={`iconfont icondanseshixintubiao-5 balance-used`}
onClick={this.useBalance}></i>
<span style={{
color: '#FF2121',
fontSize: '15px',
marginRight: "6px"
}}>{`-¥${offset}`}</span>
<i
className={`iconfont icondanseshixintubiao-5 balance-used`}
onClick={this.useBalance}
/>
</>
) : (
<i className='circle-icon' onClick={this.useBalance}></i>
......
......@@ -135,6 +135,7 @@ class Order extends Component {
Toast.info('请完善报名信息!');
}
const { location: { state ={} } } = this.props;
if(state.group === 1) {
let params = state.pdd_order_id? {
course_id: getParam("id"),
......@@ -145,8 +146,7 @@ class Order extends Component {
ischeck: this.state.useBalance,
}
http.post(`${API['base-api']}/pdd/m`, params).then(res => {
console.log(res);
if(res.data.errno === 200) {
if(Number(res.data.errno) === 200) {
sessionStorage.removeItem('orderUseCacheObj');
if (res.data.data.pay_jump === 1) {
this.props.history.push(`/togroup?id=${res.data.data.oid}`);
......@@ -154,7 +154,10 @@ class Order extends Component {
}
this.props.history.push(`/payorder?oid=${res.data.data.oid}`, {group: 1});
}else {
}else if(Number(res.data.errno) === 0){
Toast.info(res.data.data.msg, 2);
return;
} else {
Toast.info(res.data.msg, 2);
return;
}
......
......@@ -112,6 +112,15 @@ export default class PayOrder extends Component {
// 微信内部-支付
if (is_weixin()) {
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(window.location.href + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
// if(window.location.href.indexOf('aa=bb') === -1){
// localStorage.setItem('a', '第一次');
// window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(window.location.href + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
// }
// if(window.location.href.indexOf('aa=bb') > 0) {
// localStorage.setItem('a', '多次');
// let newHref = window.location.href.slice(0, window.location.href.indexOf('aa=bb')-1);
// window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=" + encodeURIComponent(newHref + "&aa=bb").toLowerCase() + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
// }
} else {
// 微信外部-支付
http.get(`${API['base-api']}/pay/wxpay/wap_charge/oid/${orderId}`).then((res) => {
......
import React, { Component } from 'react';
import React, { Component } from 'react'
import './binding-tel.scss'
import { withFormik, Field, Form } from "formik";
import { http, getParam } from "@/utils";
import { compose } from "redux";
import { connect } from "react-redux";
import { setCurrentUser } from "@/store/userAction";
import { withFormik, Field, Form } from "formik"
import { http, getParam } from "@/utils"
import { compose } from "redux"
import { connect } from "react-redux"
import { setCurrentUser } from "@/store/userAction"
import Captcha from '@/common/Captcha'
import { HeaderBar } from '@/common'
......@@ -13,147 +13,148 @@ import { HeaderBar } from '@/common'
import ClearableInput from '../common/clearableInputWithCountryCodes'
import Button from '../common/Button'
import VeriCodeInput from '../common/veriCodeInput'
import { Toast } from "antd-mobile";
import { isEmpty } from "lodash";
import { Toast } from "antd-mobile"
import { isEmpty } from "lodash"
class BindingTel extends Component {
state = {
validate: null,
captchaInstance: null
}
state = {
validate: null,
captchaInstance: null
}
getCaptchaInstance = instance => {
this.setState({
captchaInstance: instance
})
}
onVerify = (err, data) => {
if (err) {
console.log(err)
} else {
this.setState({
validate: data.validate
})
}
getCaptchaInstance = instance => {
this.setState({
captchaInstance: instance
})
}
onVerify = (err, data) => {
if (err) {
console.log(err)
} else {
this.setState({
validate: data.validate
})
}
}
render() {
const {
values,
errors,
country
} = this.props
return (
<>
<HeaderBar title={'绑定手机号'} arrow={true}/>
<div className={'binding-tel'}>
<p className={'title'}>为提高您的账号安全,请绑定手机号</p>
<Form>
<Field
name='tel'
render={({field, form}) => {
return (
<ClearableInput
{...field}
setFieldValue={form.setFieldValue}
placeholder={'请输入需要绑定的手机号'}
wrapperClass={'tel'}
country={country}
/>
render() {
const {
values,
errors,
country
} = this.props
return (
<>
<HeaderBar title={'绑定手机号'} arrow={true}/>
<div className={'binding-tel'}>
<p className={'title'}>为提高您的账号安全,请绑定手机号</p>
<Form>
<Field
name='tel'
render={({field, form}) => {
return (
<ClearableInput
{...field}
setFieldValue={form.setFieldValue}
placeholder={'请输入需要绑定的手机号'}
wrapperClass={'tel'}
country={country}
/>
)
}}
/>
<Field
name='veriCode'
render={({field}) => {
return (
<VeriCodeInput
{...field}
className={'verification'}
icon={<i className={'iconfont iconduanxin'}
style={{fontSize: '20px', left: '12px'}}
/>}
placeholder={'验证码'}
account={values.tel}
tel={values.tel}
challenge={this.state.validate}
instance={this.state.captchaInstance}
action={'auth'}
country={country}
/>
)
}}
/>
<Field
name='veriCode'
render={({field}) => {
return (
<VeriCodeInput
{...field}
className={'verification'}
icon={<i className={'iconfont iconduanxin'}
style={{fontSize: '20px', left: '12px'}}
/>}
placeholder={'验证码'}
account={values.tel}
tel={values.tel}
challenge={this.state.validate}
instance={this.state.captchaInstance}
action={'auth'}
country={country}
/>
)
}}
/>
<Captcha onVerify={this.onVerify} getInstance={this.getCaptchaInstance}/>
<Button className={'complete-btn'}
active={values.tel && values.veriCode && isEmpty(errors)}>完成</Button>
</Form>
</div>
</>
);
}
)
}}
/>
<Captcha onVerify={this.onVerify} getInstance={this.getCaptchaInstance}/>
<Button className={'complete-btn'}
active={values.tel && values.veriCode && isEmpty(errors)}>完成</Button>
</Form>
</div>
</>
)
}
}
const formikConfig = {
mapPropsToValues() {
return {
tel: '',
veriCode: ''
}
},
validateOnChange: true,
validate(values) {
let errors = {}
if (!/\d/.test(values.tel)) {
errors.tel = '请输入正确的手机号'
}
if (!values.veriCode) {
errors.veriCode = '请填写验证码'
mapPropsToValues() {
return {
tel: '',
veriCode: ''
}
},
validateOnChange: true,
validate(values) {
let errors = {}
if (!/\d/.test(values.tel)) {
errors.tel = '请输入正确的手机号'
}
if (!values.veriCode) {
errors.veriCode = '请填写验证码'
}
return errors
},
handleSubmit(values, {props}) {
http.post(`${API['passport-api']}/bind_mobile`, {
phone_num: values.tel,
phone_code: values.veriCode,
mkey: getParam('mkey'),
area_code: '00' + props.country.num,
plat: 5
}).then(res => {
const data = res.data
if (data.errno == 200) {
if (data.data['is_set_pwd']) {
const {history} = props
history.replace(`/passport/set-password`, {
user: {
hasError: false,
data: {
uid: data.data.uid
},
msg: data.data.msg,
stage: 'binding'
}
})
} else {
location.assign(data.data['jump_url'])
}
return errors
},
handleSubmit(values, {props}) {
http.post(`${API['passport-api']}/bind_mobile`, {
phone_num: values.tel,
phone_code: values.veriCode,
mkey: getParam('mkey'),
area_code: '00'+props.country.num,
plat: 5
}).then(res => {
const data = res.data
if (data.errno == 200) {
if (data.data['is_set_pwd']) {
props.setCurrentUser({
hasError: false,
data: {
uid: data.data.uid
},
msg: data.data.msg,
stage: 'binding'
})
props.history.replace(`/passport/set-password`)
} else {
location.assign(data.data['jump_url'])
}
} else {
Toast.info(data.msg, 2, null, false)
}
})
}
} else {
Toast.info(data.msg, 2, null, false)
}
})
}
}
export default compose(
connect(
state => ({country: state.country}),
{setCurrentUser}
),
withFormik(formikConfig),
)(BindingTel);
\ No newline at end of file
connect(
state => ({country: state.country}),
{setCurrentUser}
),
withFormik(formikConfig),
)(BindingTel)
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