Commit be08c70b by xuzhenghua

pull

parent c3f7e8b4
...@@ -281,7 +281,8 @@ module.exports = function(webpackEnv) { ...@@ -281,7 +281,8 @@ module.exports = function(webpackEnv) {
'react-native': 'react-native-web', 'react-native': 'react-native-web',
'@': path.resolve(__dirname, '../src'), '@': path.resolve(__dirname, '../src'),
'@common': path.resolve(__dirname, '../src/common'), '@common': path.resolve(__dirname, '../src/common'),
'@components': path.resolve(__dirname, '../src/components') '@components': path.resolve(__dirname, '../src/components'),
'@assets': path.resolve(__dirname, '../src/assets'),
}, },
plugins: [ plugins: [
// Adds support for installing with Plug'n'Play, leading to faster installs and adding // Adds support for installing with Plug'n'Play, leading to faster installs and adding
......
...@@ -1027,9 +1027,9 @@ ...@@ -1027,9 +1027,9 @@
} }
}, },
"@babel/runtime": { "@babel/runtime": {
"version": "7.7.2", "version": "7.7.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.7.tgz",
"integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", "integrity": "sha512-uCnC2JEVAu8AKB5do1WRIsvrdJ0flYx/A/9f/6chdacnEZ7LmavjdsDXr5ksYBegxtuTPR5Va9/+13QF/kFkCA==",
"requires": { "requires": {
"regenerator-runtime": "^0.13.2" "regenerator-runtime": "^0.13.2"
}, },
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
"dependencies": { "dependencies": {
"@babel/core": "7.2.2", "@babel/core": "7.2.2",
"@babel/plugin-proposal-decorators": "^7.4.4", "@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/runtime": "^7.7.7",
"@loadable/component": "^5.10.1", "@loadable/component": "^5.10.1",
"@svgr/webpack": "4.1.0", "@svgr/webpack": "4.1.0",
"antd-mobile": "^2.3.1", "antd-mobile": "^2.3.1",
...@@ -41,7 +42,9 @@ ...@@ -41,7 +42,9 @@
"jest-pnp-resolver": "1.0.2", "jest-pnp-resolver": "1.0.2",
"jest-resolve": "23.6.0", "jest-resolve": "23.6.0",
"jest-watch-typeahead": "^0.2.1", "jest-watch-typeahead": "^0.2.1",
"js-base64": "^2.5.1",
"js-cookie": "^2.2.0", "js-cookie": "^2.2.0",
"json-stringify-safe": "^5.0.1",
"less": "^3.9.0", "less": "^3.9.0",
"less-loader": "^4.1.0", "less-loader": "^4.1.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
......
...@@ -3,12 +3,13 @@ import Routes from './router' ...@@ -3,12 +3,13 @@ import Routes from './router'
import cookie from 'js-cookie' import cookie from 'js-cookie'
import { connect } from "react-redux" import { connect } from "react-redux"
import { setCurrentUser, startFetchUser } from "@/store/userAction" import { setCurrentUser, startFetchUser } from "@/store/userAction"
import {initialState} from "@/store/userReducer" import { initialState } from "@/store/userReducer"
import { withRouter, Link } from 'react-router-dom' import { withRouter, Link } from 'react-router-dom'
import { compose } from 'redux' import { compose } from 'redux'
import { getParam, http, browser } from "@/utils" import { getParam, http, browser } from "@/utils"
import { Toast } from "antd-mobile" import { Toast } from "antd-mobile"
import { addDays } from 'date-fns' import { addDays } from 'date-fns'
import stringify from 'json-stringify-safe'
//拦截ajax请求,返回mock数据 //拦截ajax请求,返回mock数据
...@@ -33,19 +34,22 @@ class App extends Component { ...@@ -33,19 +34,22 @@ class App extends Component {
pathnameBlacklist = ['/country', '/passport'] pathnameBlacklist = ['/country', '/passport']
firstLoad = true firstLoad = true
componentWillMount(){
componentWillMount() {
if (!getParam('version')) { if (!getParam('version')) {
if(!localStorage.getItem('qimoClientIdedu')){ if (!cookie.get('qimoClientIdedu')) {
this.getqimoClientId() this.getqimoClientId()
} else { } else {
window.qimoClientId = localStorage.getItem('qimoClientIdedu') window.qimoClientId = cookie.get('qimoClientIdedu')
} }
} }
} }
componentDidMount() { componentDidMount() {
this.umengStatistic() this.umengStatistic()
//平台信息 //平台信息
cookie.set('plat', '5', {domain: '.julyedu.com'}) !getParam('version') && cookie.set('plat', '5', {domain: '.julyedu.com'})
if (browser.isWeixin && browser.isIOS) { if (browser.isWeixin && browser.isIOS) {
sessionStorage.setItem('enter_url', window.location.href) sessionStorage.setItem('enter_url', window.location.href)
...@@ -70,7 +74,7 @@ class App extends Component { ...@@ -70,7 +74,7 @@ class App extends Component {
this.getUser() this.getUser()
} }
if (location.pathname === '/passport') { if (location.pathname === '/passport') {
window.localStorage.setItem('binding_redirect', JSON.stringify(this.previousLocation)) window.localStorage.setItem('binding_redirect', stringify(this.previousLocation))
} }
const {pathname, state} = location const {pathname, state} = location
if (pathname.startsWith('/passport')) { if (pathname.startsWith('/passport')) {
...@@ -285,19 +289,19 @@ class App extends Component { ...@@ -285,19 +289,19 @@ class App extends Component {
// 七陌客服代码 start // 七陌客服代码 start
getqimoClientId =()=>{ getqimoClientId = () => {
http.post(`${API['home']}/qiMoUserId`) http.post(`${API['home']}/qiMoUserId`)
.then(res => { .then(res => {
if (res.data.code == 200) { if (res.data.code == 200) {
window.qimoClientId = res.data.data.userId window.qimoClientId = res.data.data.userId
localStorage.setItem('qimoClientIdedu', res.data.data.userId) cookie.set('qimoClientIdedu', res.data.data.userId, {domain: '.julyedu.com'})
} }
}) })
.catch(function () { .catch(function () {
}) })
} }
QimoClient=()=>{ QimoClient = () => {
let utm_source = getParam('utm_source') let utm_source = getParam('utm_source')
let utm_medium = getParam('utm_medium') let utm_medium = getParam('utm_medium')
let utm_campaign = getParam('utm_campaign') let utm_campaign = getParam('utm_campaign')
...@@ -307,10 +311,10 @@ class App extends Component { ...@@ -307,10 +311,10 @@ class App extends Component {
var src = '' var src = ''
// 知乎投放 // 知乎投放
if (utm_term && utm_source && utm_medium && utm_campaign && utm_content) { if (utm_term && utm_source && utm_medium && utm_campaign && utm_content) {
src = 'https://webchat.7moor.com/javascripts/7moorInit.js?accessId=e2ca4f90-2d04-11ea-84c3-43908ae47640&autoShow=true&language=ZHCN' src = 'https://webchat.7moor.com/javascripts/7moorInit.js?accessId=e2ca4f90-2d04-11ea-84c3-43908ae47640&autoShow=false&language=ZHCN'
} else { } else {
// m端 // m端
src = 'https://webchat.7moor.com/javascripts/7moorInit.js?accessId=fbcf9aa0-2d03-11ea-84c3-43908ae47640&autoShow=true&language=ZHCN' src = 'https://webchat.7moor.com/javascripts/7moorInit.js?accessId=fbcf9aa0-2d03-11ea-84c3-43908ae47640&autoShow=false&language=ZHCN'
} }
var script = document.createElement('script') var script = document.createElement('script')
...@@ -320,12 +324,17 @@ class App extends Component { ...@@ -320,12 +324,17 @@ class App extends Component {
document.body.appendChild(script) document.body.appendChild(script)
} }
// 七陌客服代码 end
// 七陌客服代码 end
render() { render() {
return <Routes/> return <>
<Routes/>
{/*<Link className={'year19-index'} to="/year/yearindex">*/}
{/*<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/PC/pc-yearindex.png" alt=""/>*/}
{/*</Link>*/}
</>
} }
} }
......
...@@ -512,3 +512,18 @@ input[type="radio"]:checked:before { ...@@ -512,3 +512,18 @@ input[type="radio"]:checked:before {
color: #333; color: #333;
font-size: 15px; font-size: 15px;
} }
.year19-index {
display: block;
width: 58px;
height: 70px;
position: fixed;
top: 50%;
right: 0;
margin-top: -35px;
z-index: 9;
img {
width: 100%;
height: 100%;
}
}
\ No newline at end of file
...@@ -19,7 +19,7 @@ const options = { ...@@ -19,7 +19,7 @@ const options = {
}, },
appstore: "https://itunes.apple.com/cn/app/id1102275343?mt=8", appstore: "https://itunes.apple.com/cn/app/id1102275343?mt=8",
yingyongbao: "http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline", yingyongbao: "http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline",
fallback: "http://www.julyedu.com/weekend/redir1" fallback: "http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline"
} }
class OpenApp extends Component { class OpenApp extends Component {
...@@ -38,7 +38,7 @@ class OpenApp extends Component { ...@@ -38,7 +38,7 @@ class OpenApp extends Component {
}, },
callback: () => { callback: () => {
window.location.href = "http://www.julyedu.com/weekend/redir1"; window.location.href = "http://android.myapp.com/myapp/detail.htm?apkName=com.julyapp.julyonline";
} }
}); });
} }
......
#give-courses {
@mixin px2px($name, $px) {
#{$name}: round($px / 2) * 1px;
}
@function px2rem($px) {
@return #{$px}px
}
background: #3d1aaf;
padding-bottom: px2rem(45);
.banner {
width: 100%;
height: 187.5px;
img {
width: 100%;
height: 100%;
}
}
.give-box {
background-color: #1c008c;
box-shadow: 0 0 4px 0 #1c008c;
margin: px2rem(10);
padding: px2rem(10) px2rem(5) 0 px2rem(5);
.give-course {
width: 100%;
height: px2rem(125);
background-color: #fff;
border-radius: 2px;
margin-bottom: px2rem(10);
padding: px2rem(8) px2rem(5);
display: flex;
justify-content: space-between;
.give-course-img {
width: px2rem(150);
height: px2rem(108);
img {
width: 100%;
height: 100%;
}
}
.give-course-mess {
width: px2rem(178);
height: px2rem(108);
margin-left: px2rem(7);
position: relative;
text-align: left;
.course-title {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.course-title a {
color: #353535;
@include px2px(font-size, 26);
}
.course-teacher {
@include px2px(font-size, 24);
color: #666;
margin-top: px2rem(12);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.course-time {
@include px2px(font-size, 24);
color: #666;
margin-top: px2rem(7);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tag {
display: inline-block;
color: #555;
background-color: #f2f2f2;
margin-right: px2rem(4);
padding: px2rem(2) px2rem(4);
}
.toreceive {
width: px2rem(93);
height: px2rem(24);
@include px2px(font-size, 24);
color: #fff;
background-color: #09f;
border-radius: 4px;
line-height: px2rem(24);
text-align: center;
position: absolute;
bottom: 0;
}
}
}
.rule-title {
color: #2ff8ff;
@include px2px(font-size, 32);
text-align: left;
padding-left: px2rem(5);
}
.rule-list {
text-align: left;
color: #fff;
@include px2px(font-size, 24);
padding-left: px2rem(5);
}
.marquee_box {
width: px2rem(355);
height: px2rem(30);
overflow: hidden;
background-color: rgba(0, 0, 0, .5);
margin-left: px2rem(-5);
margin-top: px2rem(15);
.marquee_list {
li {
color: #fff;
height: px2rem(30);
line-height: px2rem(30);
@include px2px(font-size, 24);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
img {
width: px2rem(18);
height: px2rem(18);
vertical-align: middle;
border-radius: 50%;
}
span {
color: #0099ff;
display: inline-block;
margin: 0 5px;
}
}
}
.marquee_top {
transition: all .5s;
margin-top: -30px;
}
}
}
.set-prize {
background-color: #FCECB1;
border-radius: px2rem(3);
margin: px2rem(20) px2rem(10) 0 px2rem(10);
padding: px2rem(18) px2rem(15) px2rem(20) px2rem(15);
.set-prize-title {
width: 100%;
text-align: center;
color: #F75E18;
@include px2px(font-size, 28);
img {
width: px2rem(19);
height: px2rem(19);
margin-right: px2rem(10);
vertical-align: sub;
}
}
.set-prize-content {
text-align: left;
color: #6E1517;
@include px2px(font-size, 24);
display: flex;
flex-wrap: wrap;
p {
margin-top: px2rem(12);
}
}
}
.ranking-list {
margin: px2rem(30) px2rem(10) 0 px2rem(10);
.ranking_title {
width: 100%;
text-align: center;
img {
width: px2rem(18);
height: px2rem(20);
vertical-align: text-bottom;
}
span {
color: #fff;
@include px2px(font-size, 28);
display: inline-block;
margin-left: px2rem(10);
}
p {
color: #fee600;
@include px2px(font-size, 24);
margin-top: 10px;
}
}
table {
text-align: center;
margin-top: px2rem(15);
box-shadow: 0 0 5px 0 rgba(0, 0, 0, .3);
width: 100%;
border-radius: 6px 6px 0 0;
overflow: hidden;
thead tr {
background-color: #fadc7f;
height: px2rem(30);
line-height: px2rem(30);
@include px2px(font-size, 26);
color: #ad4700;
}
tbody tr:nth-of-type(even) {
background-color: #fadc7f;
height: px2rem(35);
}
tbody tr:nth-of-type(odd) {
background-color: #ffe794;
height: px2rem(35);
}
tbody tr {
color: #333;
@include px2px(font-size, 24);
}
tbody tr td {
width: 30%;
}
tbody tr td:nth-child(2) {
text-align: left;
padding-left: px2rem(15);
}
tbody tr td:nth-child(2) span {
display: inline-block;
width: 55%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
position: relative;
top: 5px;
margin-left: px2rem(5);
}
tbody tr td:nth-child(1) img {
vertical-align: middle;
width: px2rem(18);
height: px2rem(22);
}
tbody tr td:nth-child(2) img {
width: px2rem(20);
height: px2rem(20);
vertical-align: middle;
border-radius: 50%;
}
tbody .ismylist td {
background-color: #ad4700;
color: #fff;
}
}
.btm {
width: 100%;
height: px2rem(10);
background-color: #ffe794;
border-radius: 0 0 6px 6px;
}
}
.julynotice {
margin: px2rem(60) auto px2rem(30) auto;
color: #FEE600;
@include px2px(font-size, 13);
text-align: center;
}
.code-mbc {
position: fixed;
left: 0;
width: 100%;
top: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .5);
z-index: 9;
text-align: center;
.code-box {
width: 80%;
background-color: #fff;
border-radius: px2rem(10);
text-align: center;
margin: px2rem(200) auto 0 auto;
padding-top: px2rem(15);
.code-title {
color: #333;
@include px2px(font-size, 36);
i {
color: #f00;
@include px2px(font-size, 36);
font-style: normal;
}
}
#qrCodeWpay {
width: px2rem(150);
height: px2rem(150);
margin: px2rem(10) auto 0 auto;
}
.btmmess {
color: #666;
padding-bottom: px2rem(15);
margin-top: px2rem(-5);
}
}
.close {
display: inline-block;
@include px2px(font-size, 60);
color: #fff;
margin-top: px2rem(20);
}
}
}
import React, { Component } from 'react'
import './give-courses.scss'
import { getParam, http } from "@/utils"
import { Toast } from "antd-mobile"
import { Link } from "react-router-dom"
function showToast(text) {
Toast.info(text, 2, null, false)
}
class GiveCourses extends Component {
state = {
banner: '',
courses: [],
rule: '',
awardstext: '',
rankList: {},
isShow: false,
animate: false,
marqueeList: []
}
componentDidMount() {
http.get(`${API["base-api"]}/assistance/detail`)
.then(res => {
const {data, errno, msg} = res.data
if (errno === 200) {
this.setState({
banner: data["active_info"]["m_banner"],
courses: data.course_info,
rule: data["active_info"]["rule"],
awardstext: data["active_info"]["awards_text"].split('\n\n'),
query: data["active_info"]["activity_name"]
})
this.isRouter(data["active_info"]["activity_name"])
} else {
showToast(msg)
}
})
this.getRankList()
this.getMarqueeList()
setInterval(this.showMarquee, 5000)
setInterval(this.getMarqueeList, 60000)
}
getRankList = () => {
http.get(`${API["base-api"]}/assistance/ranking_list/50`)
.then(res => {
const {data, errno, msg} = res.data
if (errno === 200) {
this.setState({
rankList: {
list: data.list,
first: data.list[0],
second: data.list[1],
third: data.list[2],
other: data.list.slice(3, 50),
isMyList: data["nickname"],
myList: data["nickname"] && data
}
})
} else {
showToast(msg)
}
})
}
getMarqueeList = () => {
http.get(`${API["base-api"]}/assistance/roll_tip`)
.then(res => {
const {errno, msg, data} = res.data
if (errno === 200) {
this.setState({
marqueeList: data
})
} else {
showToast(msg)
}
})
}
showMarquee = () => {
this.setState({
animate: true
}, () => {
setTimeout(() => {
const [first, second] = this.state.marqueeList
this.setState({
animate: false,
marqueeList: [second, first]
})
}, 500)
})
}
isRouter = param => {
if (decodeURIComponent(getParam('activename')) != param) {
this.props.history.push('/')
}
}
render() {
const {
banner,
courses,
rule,
awardstext,
rankList,
isShow,
animate,
marqueeList
} = this.state
return (
<div id={'give-courses'}>
<div className="banner">
<img src={banner} alt=""/>
</div>
<div className='give-box'>
{
courses.map(course => {
return (
<div className='give-course' key={course.id}>
<Link className='give-course-img' to={`/detail?id=${course.course_id}`}>
<img src={course.image_name} alt=""/>
</Link>
<ul className="give-course-mess">
<li className='course-title'>
<a href="javascript:">{course.course_title}</a>
</li>
<li className='course-teacher'><span className='tag'>讲师</span>{course["teachers"]}</li>
<li className='course-time'><span className='tag'>开课时间</span>{course["start_time"]}</li>
<li className='toreceive' onClick={() => {
_czc && _czc.push(["_trackEvent", `课程id=${course.course_id}`, '免费领取课程'])
console.log(course.course_id)
this.setState({isShow: true})
}}>免费领取课程
</li>
</ul>
</div>
)
})
}
<p className="rule-title">活动规则</p>
<div className="rule-list" dangerouslySetInnerHTML={{__html: rule}}/>
<div className="marquee_box">
<ul className={`marquee_list ${animate ? 'marquee_top' : ''}`}>
{
marqueeList.length ?
marqueeList.map((item, index) => {
return (
<li key={index}>
<img src={item.head_img} alt=""/>
<span>{item["nickname"]}</span>
{item["word"]}
</li>
)
})
: null
}
</ul>
</div>
</div>
<div className="set-prize">
<p className="set-prize-title">
<img src="//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018_1111/jpsz_icon.png"
alt=""/>奖品设置
</p>
<div className="set-prize-content">
{
awardstext && awardstext.length && awardstext.map((item, index) => <p key={index}>{item}</p>)
}
</div>
</div>
<div className="ranking-list">
<div className="ranking_title">
<img src="//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018_1111/jbei_icon.png" alt=""/>
<span>排行榜</span>
<p>数据实时更新 只显示Top50</p>
</div>
<table border="0" cellPadding="0" cellSpacing="0">
<thead>
<tr>
<td>排名</td>
<td>用户</td>
<td>邀请人数</td>
</tr>
</thead>
<tbody>
{
rankList.list && rankList.list.length > 0
?
<tr>
<td><img src="//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018_1111/jin1_icon.png" alt=""/></td>
<td><img src={rankList.first.head_img} alt=""/><span>{rankList.first.name}</span></td>
<td>{rankList.first.num}</td>
</tr>
: null
}
{
rankList.list && rankList.list.length > 1
?
<tr>
<td><img src="//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018_1111/yin2_icon.png" alt=""/></td>
<td><img src={rankList.second.head_img} alt=""/><span>{rankList.second.name}</span></td>
<td>{rankList.second.num}</td>
</tr>
: null
}
{
rankList.list && rankList.list.length > 2
?
<tr>
<td><img src="//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018_1111/tong_icon.png" alt=""/></td>
<td><img src={rankList.third.head_img} alt=""/><span>{rankList.third.name}</span></td>
<td>{rankList.third.num}</td>
</tr>
: null
}
{
rankList.list && rankList.list.length && rankList.list.length > 3 ? rankList.other.map((item, index) => {
return (
<tr key={index}>
<td>{index + 4}</td>
<td><img src={item.head_img} alt=""/><span>{item.name}</span></td>
<td>{item.num}</td>
</tr>
)
})
: null
}
{
rankList.isMyList &&
<tr className="ismylist">
<td>{rankList.myList["ranking"]}</td>
<td><img src={rankList.myList.head_img} alt=""/><span>{rankList.myList["nickname"]}</span></td>
<td>{rankList.myList["inviter_num"]}</td>
</tr>
}
</tbody>
</table>
<p className="btm"/>
</div>
<p className="julynotice">*本活动最终解释权归七月在线所有*</p>
{
isShow &&
<div className="code-mbc">
<div className="code-box">
<p className="code-title">进入服务号回复<i>77</i>免费领取课程</p>
<img id="qrCodeWpay" src="//julyedu-cdn.oss-cn-beijing.aliyuncs.com/2018christyear/h5/qrcode.jpg" alt=""/>
<p className="btmmess">长按扫码进入服务号</p>
</div>
<i className="close iconfont iconiconfront-2" onClick={() => {
this.setState({isShow: false})
}}/>
</div>
}
</div>
)
}
}
export default GiveCourses
import React, { Component } from 'react'
import './share-content.scss'
import Poster from "./poster/poster"
import Prizes from './prizes/prizes'
import {WithFullSize} from '@/HOCs'
class ShareContent extends Component {
state = {
activeIndex: 0,
tabs: ['分享海报', '活动奖品'],
poster: '',
rankingList: []
}
render() {
const {
tabs,
activeIndex,
poster,
rankingList
} = this.state
return (
<div id={'share-content'}>
<ul className="tab">
{
tabs.map((item, index) => {
return (
<li key={index} className={activeIndex === index ? 'active' : ''} onClick={() => {
this.setState({activeIndex: index})
}}>{item}</li>
)
})
}
</ul>
{
activeIndex === 0
? <Poster
poster={poster}
savePoster={poster => {
this.setState({poster})
}}/>
: <Prizes rankingList={rankingList} saveRankingList={rankingList => {this.setState({rankingList})}}/>
}
</div>
)
}
}
export default WithFullSize(ShareContent)
import React, { Component } from 'react'
import QRCode from "qrcode"
import './poster.scss'
import { getParam, http } from "@/utils"
import { Toast } from "antd-mobile"
function showToast(text) {
Toast.info(text, 2, null, false)
}
class Poster extends Component {
state = {
redirectUrl: '',
backgroundUrl: '',
avatar: '',
username: '',
poster: this.props.poster,
}
componentDidMount() {
const {poster} = this.props
if (!poster) {
http.get(`${API["base-api"]}/assistance/active_haibao_info/${getParam('assis_word')}`)
.then(res => {
const {data, errno, msg} = res.data
if (errno === 200) {
this.setState({
avatar: data.head_img,
username: data.user_name,
redirectUrl: data.m_redirect_code,
backgroundUrl: data.background_img_url
}, () => {
this.generatePoster()
})
} else {
showToast(msg)
}
})
}
}
generatePoster = async () => {
let canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
posterWidth = 270,
canvasWidth = 540
const {backgroundUrl, avatar, username, redirectUrl} = this.state
const bg = await this.getImage(backgroundUrl)
canvas.style.width = posterWidth + 'px'
canvas.style.height = posterWidth * bg.height / bg.width + 'px'
canvas.width = canvasWidth
canvas.height = canvasWidth * bg.height / bg.width
ctx.drawImage(bg, 0, 0, canvas.width, canvas.height)
let r = 33
const avatarImage = await this.getImage(avatar)
const ax = 40
const ay = 16
ctx.save()
ctx.beginPath()
ctx.arc(ax + r, ay + r, r, 0, Math.PI * 2)
ctx.clip()
ctx.drawImage(avatarImage, ax, ay, 66, 66)
ctx.restore()
ctx.font = `24px serif`
ctx.fillStyle = '#fff'
ctx.fillText(username, 2 * r + ax + 10, ay + r - 5)
let qrcode = await this.getQRCodeCanvas(redirectUrl, posterWidth)
ctx.drawImage(qrcode, 380, 796, 140, 140)
this.setState({
poster: canvas.toDataURL()
}, () => {
const {savePoster} = this.props
savePoster && savePoster(this.state.poster)
})
}
getImage = url => {
return new Promise(resolve => {
const img = new Image()
img.setAttribute('crossOrigin', 'anonymous')
img.onload = function () {
resolve(this)
}
img.src = url
})
}
getQRCodeCanvas = (text, posterWidth) => {
const canvas = document.createElement('canvas')
let codeWidth = 100, codeHeight = 100,
codeSize = posterWidth * (100 / (window.innerWidth * 0.72))
canvas.style.width = `${codeSize}px`
canvas.style.height = `${codeSize}px`
canvas.width = codeWidth
canvas.height = codeHeight
return QRCode.toCanvas(canvas, text)
}
render() {
const {poster} = this.state
return (
<div id='poster'>
<div className="placard-desc">
长按下方海报,分享给好友~
</div>
<div className="total-container">
<div className="placard-img-container" id='imgWrapper'>
<img src={poster} alt='分享海报'/>
</div>
</div>
</div>
)
}
}
export default Poster
#poster {
width: 100%;
height: 100%;
overflow: hidden;
background-color: #470bc8;
-webkit-overflow-scrolling: touch;
-webkit-touch-callout: none;
.placard-desc {
width: 100%;
color: #fff;
background-color: #470bc8;
font-size: 14px;
margin-bottom: 15px;
}
.total-container {
width: 100%;
height: 90%;
position: relative;
.placard-img-container {
width: 100%;
position: relative;
img {
width: 72%;
}
}
}
}
import React, { Component } from 'react'
import './prizes.scss'
import { http } from "@/utils"
import { Toast } from "antd-mobile"
function showToast(text) {
Toast.info(text, 2, null, false)
}
class Prizes extends Component {
state = {
list: [
'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/prize-1.png',
'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/prize-2.png',
'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/prize-3.png',
'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/prize-4.png',
'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/prize-5.png',
'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/prize-6.png',
],
isShowRule: false,
rankList: []
}
componentDidMount() {
const {rankingList} = this.props
console.log(rankingList)
if (!rankingList || !rankingList.length) {
this.getRankingList()
} else {
this.setState({
rankingList
})
}
}
getRankingList = () => {
const {saveRankingList} = this.props
http.get(`${API["base-api"]}/assistance/ranking_list/50`)
.then(res => {
const {data, msg, errno} = res.data
if (errno === 200) {
this.setState({
rankList: data.list
})
saveRankingList && saveRankingList(data.list)
} else {
showToast(msg)
}
})
}
render() {
const {
list,
rankList,
isShowRule
} = this.state
return (
<div id={'prizes'}>
<div className="content">
<i className="part-title__decorate"/>
<div className="part-title__txt">活动奖品</div>
<i className="part-title__decorate"/>
<div className="prize-img">
{
list.map((item, index) => {
return (
<div className='img-box' key={index}>
<img src={item} alt=""/>
</div>
)
})
}
</div>
<span className="rule" onClick={() => {
this.setState({isShowRule: true})
}}>活动规则</span>
</div>
<div className="content" style={{padding: `20px 0 30px 0`}}>
<i className="part-title__decorate"/>
<div className="part-title__txt">排行榜</div>
<i className="part-title__decorate"/>
<div className="tip">
数据实时更新 只显示Top50
</div>
<table className="ranking" cellSpacing="0" cellPadding="0" border="0">
<thead>
<tr>
<td>排名</td>
<td>用户名称</td>
<td>邀请人数</td>
</tr>
</thead>
<tbody>
{
rankList.map((item, index) => {
return (
<tr key={index}>
<td>{index + 1}</td>
<td>{item.name}</td>
<td>{item.num}</td>
</tr>
)
})
}
</tbody>
</table>
</div>
{
isShowRule ?
<div className="mbc-box">
<div className="rele-content">
<div className="title">活动规则</div>
<p>1、进入七月在线服务号<a
style={{fontSize: `16px`, color: `rgba(47, 248, 255, 1)`, display: `inline-block`}}>回复77</a>获取活动海报,将上方课程赠送给好友,每有1名好友领取后,您和好友均可免费学习1课时该课
</p>
<p>2、每多1名好友领取,您获得的课时数+1,直到获得全部课时,届时仍可赠送给好友;</p>
<p>3、活动结束后,邀请好友数超过50人且排行榜前20名用户会得到<a
style={{fontSize: `16px`, color: `rgba(47, 248, 255, 1)`, display: `inline-block`}}>19VIP年会员、樱桃键盘</a>等大奖
</p>
</div>
<img className="close"
onClick={() => {this.setState({isShowRule: false})}}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/close-btn.png" alt=""/>
</div>
: null
}
</div>
)
}
}
export default Prizes
#prizes {
padding: 0 10px;
height: auto;
.content {
padding: 20px 10px 30px 10px;
background-color: #3F07B8;
border: 1px solid #5970FF;
border-radius: 4px;
text-align: center;
margin-bottom: 30px;
}
.part-title__decorate {
display: block;
width: 232px;
height: 2px;
margin: 0 auto;
background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 48%, rgba(255, 255, 255, 0) 100%);
}
.part-title__txt {
display: inline-block;
height: 32px;
line-height: 32px;
font-size: 16px;
color: #fff;
font-weight: 400;
letter-spacing: 2px;
}
.prize-img {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
margin-top: 20px;
.img-box {
width: 31.3%;
height: 112px;
margin-bottom: 5px;
img {
width: 100%;
height: 100%;
}
}
}
.rule {
display: inline-block;
width: 101px;
height: 28px;
line-height: 28px;
border: 1px solid rgba(254, 228, 29, 1);
border-radius: 14px;
margin-top: 15px;
color: #FEE41D;
font-size: 15px;
}
.tip {
margin-top: 15px;
font-size: 12px;
color: #fff;
}
.ranking {
width: 100%;
margin-top: 20px;
tr {
height: 44px;
line-height: 44px;
}
thead {
color: #FEE41D;
font-size: 14px;
font-weight: 500;
background-color: #490AD1;
}
tbody {
color: #fff;
font-weight: 400;
font-size: 12px;
tr {
td:first-child {
font-size: 14px;
}
}
tr:nth-child(odd) {
background-color: #470AC9;
}
tr:nth-child(even) {
background-color: #490AD1;
}
}
}
}
.mbc-box{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .6);
.rele-content {
display: inline-block;
width: 320px;
background: #fff;
border-radius: 5px;
padding: 20px 28px 30px 28px;
box-sizing: border-box;
margin: 145px auto 30px auto;
.title {
font-size: 18px;
color: #111;
margin-bottom: 20px;
font-weight: normal;
}
p {
text-align: left;
font-size: 14px;
color: #666666;
line-height: 18px;
margin-bottom: 3px;
}
}
.close {
display: block;
margin: auto;
width: 33px;
height: 33px;
}
}
#share-content {
width: 100%;
height: auto;
min-height: 100%;
background-color: #470bc8;
padding: 30px 0 40px 0;
position: relative;
text-align: center;
font-family: Microsoft YaHei,Helvetica Neue,STHeiti,Helvetica,Arial,sans-serif;
.tab {
display: flex;
justify-content: center;
margin: 0 auto 20px auto;
li {
width: 83px;
height: 32px;
line-height: 32px;
color: #FEE41D;
border: 1px solid #FEE41D;
font-size: 16px;
background-color: #470bc8;
}
li:first-child {
border-radius: 4px 0 0 4px;
}
li:last-child {
border-radius: 0 4px 4px 0;
}
.active {
color: #090F08;
background: #FEE41D;
border: 1px solid #FEE41D;
}
}
}
...@@ -114,7 +114,7 @@ class Prizes extends Component { ...@@ -114,7 +114,7 @@ class Prizes extends Component {
item.grant_max item.grant_max
? ?
<div className='bottom-bar'> <div className='bottom-bar'>
<div className="progress-bar"><span className={'progress'}/></div> <div className="progress-bar"><span className={'progress'} style={{width: `${(item.surplus / item.grant_max) * 100}%`}}/></div>
<span>限量{item.grant_max}</span> <span>限量{item.grant_max}</span>
</div> </div>
: <span className='no-limit'>不限量</span> : <span className='no-limit'>不限量</span>
......
...@@ -178,7 +178,7 @@ ...@@ -178,7 +178,7 @@
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
width: 80%; //width: 80%;
height: 100%; height: 100%;
background: linear-gradient(-90deg, rgba(255, 140, 0, 1) 0%, rgba(255, 23, 0, 1) 100%); background: linear-gradient(-90deg, rgba(255, 140, 0, 1) 0%, rgba(255, 23, 0, 1) 100%);
border-radius: 1px; border-radius: 1px;
......
...@@ -43,7 +43,7 @@ class MyTreasure extends Component { ...@@ -43,7 +43,7 @@ class MyTreasure extends Component {
componentDidMount() { componentDidMount() {
this.fetchMyTreasure() this.fetchMyTreasure()
this.fetchActivityStatus() this.fetchActivityStatus()
document.title = '七月在线年终大回馈,幸运宝箱随你开,100%有奖!人气好课免费学,精品课程1分抢!'; document.title = '七月在线新春献礼,幸运宝箱随你开,100%有奖!“薪”年好课免费学,精品课程1分秒!';
} }
componentWillReceiveProps(nextProp) { componentWillReceiveProps(nextProp) {
......
...@@ -141,7 +141,7 @@ class LiveRoom extends Component { ...@@ -141,7 +141,7 @@ class LiveRoom extends Component {
) )
} }
<CommonContainer title='大咖直播' id="year-live"> <CommonContainer title='“薪”年好课免费学' id="year-live">
<ul className='live__list'> <ul className='live__list'>
{ {
list.length && ( list.length && (
...@@ -153,39 +153,39 @@ class LiveRoom extends Component { ...@@ -153,39 +153,39 @@ class LiveRoom extends Component {
<span>主题:</span> <span>主题:</span>
<p>{item.title}</p> <p>{item.title}</p>
</div> </div>
<div className="info__item"> {/*<div className="info__item">*/}
<span>时间:</span> {/*<span>时间:</span>*/}
<p>{item.date}</p> {/*<p>{item.date}</p>*/}
</div> {/*</div>*/}
<div className="info__item"> <div className="info__item">
<span>讲师:</span> <span>讲师:</span>
<p>{item.teacher}</p> <p>{item.teacher}</p>
</div> </div>
{ {/*{*/}
item.on_live == 0 && item.is_end == 0 && item.is_subscribe == 0 && ( {/*item.on_live == 0 && item.is_end == 0 && item.is_subscribe == 0 && (*/}
<span onClick={ ()=>this.subscribe(item.live_id)} className="order__btn">立即预约</span> {/*<span onClick={ ()=>this.subscribe(item.live_id)} className="order__btn">立即预约</span>*/}
) {/*)*/}
} {/*}*/}
{ {/*{*/}
item.is_end == 1 && item.transcribe_url=='' && ( {/*item.is_end == 1 && item.transcribe_url=='' && (*/}
<span className="order__btn live__end">已结束</span> {/*<span className="order__btn live__end">已结束</span>*/}
) {/*)*/}
} {/*}*/}
{/*{*/}
{/*item.on_live == 0 && item.is_end == 0 && item.is_subscribe == 1 && (*/}
{/*<span onClick={this.tip} className="order__btn subscribed">已预约</span>*/}
{/*)*/}
{/*}*/}
{/*{*/}
{/*item.on_live == 1 && item.is_end == 0 && (*/}
{/*<span onClick={()=>this.toLivingRoom(item.room_url)} className="order__btn living">正在直播</span>*/}
{/*)*/}
{/*}*/}
{ {
item.on_live == 0 && item.is_end == 0 && item.is_subscribe == 1 && ( item.transcribe_url != '' && (
<span onClick={this.tip} className="order__btn subscribed">已预约</span> <span onClick={() => this.checkVideo(item.transcribe_url)} className="order__btn check__video">点击查看</span>
)
}
{
item.on_live == 1 && item.is_end == 0 && (
<span onClick={()=>this.toLivingRoom(item.room_url)} className="order__btn living">正在直播</span>
)
}
{
item.is_end == 1 && item.transcribe_url != '' && (
<span onClick={() => this.checkVideo(item.transcribe_url)} className="order__btn check__video">查看回放</span>
) )
} }
......
...@@ -10,6 +10,36 @@ ...@@ -10,6 +10,36 @@
margin: 12px auto 0; margin: 12px auto 0;
} }
.course-conter {
.course-item {
width: 168px;
padding: 4px;
background-color: #fff;
position: relative;
border-radius: 2px;
span {
position: absolute;
right: 4px;
top: 4px;
width: 60px;
display: block;
text-align: center;
padding-left: 5px;
border-radius: 0 0 0 10px;
background-color: #EB1612;
color: #fff;
font-size: 12px;
}
a {
width: 160px;
height: 104px;
img {
width: 100%;
height: 100%;
}
}
}
}
.course-box { .course-box {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
......
...@@ -29,7 +29,7 @@ export default class index extends Component { ...@@ -29,7 +29,7 @@ export default class index extends Component {
userInfo: {}, userInfo: {},
isAppUpdate: false, isAppUpdate: false,
showMark: false, showMark: false,
banner: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_banner_bj%402x.png' banner: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/new-year/m-banner.png'
} }
componentDidMount() { componentDidMount() {
...@@ -39,7 +39,7 @@ export default class index extends Component { ...@@ -39,7 +39,7 @@ export default class index extends Component {
_this.loginInfo(result) _this.loginInfo(result)
} }
_this.getStage() _this.getStage()
document.title = '七月在线年终大回馈,幸运宝箱随你开,100%有奖!人气好课免费学,精品课程1分抢!'; document.title = '七月在线新春献礼,幸运宝箱随你开,100%有奖!“薪”年好课免费学,精品课程1分秒!';
} }
// 获取app登录数据 // 获取app登录数据
...@@ -147,7 +147,7 @@ export default class index extends Component { ...@@ -147,7 +147,7 @@ export default class index extends Component {
}) })
} else { } else {
this.setState({ this.setState({
banner: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_banner_bj%402x.png', banner: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/new-year/m-banner.png',
}) })
} }
} else { } else {
......
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
} }
.banner-treasure__decorate { .banner-treasure__decorate {
height: 35px; height: 20px;
background-size: cover; //background-size: cover;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_nv_bj%402x.png'); //background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/newyear20/H5/m_nv_bj%402x.png');
} }
.sub__code_container { .sub__code_container {
......
...@@ -13,20 +13,24 @@ class TreasureNav extends Component { ...@@ -13,20 +13,24 @@ class TreasureNav extends Component {
navs: [ navs: [
{ {
id: 'year-live', id: 'year-live',
name: '大咖直播' name: '好课免费学'
}, },
{ {
id: 'year-treasure', id: 'year-treasure',
name: '组队开宝箱' name: '组队开宝箱'
}, },
{ {
id: 'year-course', id: 'year-wuhan',
name: '重磅好课' name: '驰援武汉'
}, },
{ {
id: 'year-free', id: 'year-course',
name: '免费学' name: '重磅好课'
}, },
// {
// id: 'year-free',
// name: '免费学'
// },
{ {
id: 'year-group', id: 'year-group',
name: '1分拼团' name: '1分拼团'
......
import React from 'react';
import './banner.scss';
export default (props) => {
const { banner = '' } = props;
const style = () => {
if(banner) {
return {
backgroundImage: `url(${banner})`
}
}
return {};
}
return (
<div className="college-banner"></div>
)
}
\ No newline at end of file
.college-banner {
height: 100px;
// background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/college-plan/college-banner.png');
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/college-plan/m-banner.png');
background-size: cover;
}
\ No newline at end of file
import React, { Component } from 'react';
import { http } from '@/utils';
import { HeaderBar } from "@/common";
import CollegeBanner from './banner';
import CollegeHeader from './header';
import './courseList.scss';
import { Toast } from 'antd-mobile';
class CollegeCourse extends Component {
constructor(props) {
super(props);
this.state = {
header: '',
courseList: []
};
}
componentDidMount() {
this.fetchCourseList();
}
fetchCourseList = () => {
const { match } = this.props;
const id = match.params.id || 0;
http.get(`${API['home']}/sys/school/${id}`).then(res => {
const { code, data } = res.data;
if(code === 200) {
this.setState({
header: data.name,
courseList: data.data
});
document.title = `助力高校在线教学计划之${data.name}专区 - 七月在线`
}
});
}
toCourseDetail = (id) => {
const { history, match } = this.props;
const school_id = match.params.id || 0
http.post(`${API['home']}/sys/school/verify`, {
school_id,
course_id: id,
}).then(res => {
const { code, msg } = res.data;
if(code === 200) {
history.push(`/detail?id=${id}`);
}else if(code === 4030 || code === 4013) {
history.push('/passport/login');
}else {
Toast.info(`${msg}~`);
}
});
}
render() {
const { courseList = [], header } = this.state;
return (
<>
<HeaderBar title={'助学计划'} arrow={true}/>
<CollegeBanner />
<CollegeHeader
headerStyle={{
marginTop: '20px'
}}
title={header}
/>
<p className="college-course__desc">点击需要学习的课程封面,在课程详情页进入购买流程凭免单券免费兑换课程。</p>
<div className="college-course__body">
{
courseList.map(item => (
<div
className="college-course__item"
onClick={() => this.toCourseDetail(item.course_id)}
key={item.course_id}
>
<i className="college-course__cover" style={{'backgroundImage': `url(${item.image_name})`}}></i>
<p className="college-course__title">{item.course_title}</p>
</div>
))
}
</div>
</>
)
}
}
export default CollegeCourse;
\ No newline at end of file
.college-course__desc {
margin: 8px 19px 12px;
font-size: 12px;
color: #0099FF;
text-align: center;
line-height: 15px;
}
.college-course__body {
display: flex;
flex-wrap: wrap;
padding: 0 7px;
}
.college-course__item {
width: 165px;
height: 162px;
margin: 0 7px 15px;
border-radius: 4px;
background-color: #fff;
box-shadow: 0px 0px 8px 0px rgba(153,153,153,0.2);
overflow: hidden;
}
.college-course__cover {
display: block;
height: 119px;
background-repeat: no-repeat;
background-position: center;
background-size: auto 100%;
}
.college-course__title {
display: -webkit-box;
margin: 8px 0 0;
padding-left: 5px;
font-size: 14px;
color: #525C65;
line-height: 16px;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
/* autoprefixer: ignore next */
-webkit-box-orient: vertical;
}
\ No newline at end of file
import React from 'react';
import './header.scss';
export default (props) => {
const { title, isDecorate = true, headerStyle = {} } = props;
return (
<>
<div className="college-header" style={headerStyle}>
<i className="college-header__icon" data-direction="left"></i>
<h2 className="college-header__text">{title}</h2>
<i className="college-header__icon" data-direction="right"></i>
</div>
{
isDecorate &&
<i className="college-header__decorate"></i>
}
</>
);
};
.college-header {
display: flex;
justify-content: center;
align-items: center;
height: 34px;
}
.college-header__icon {
width: 44px;
height: 8px;
background-size: cover;
&[data-direction="left"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/college-plan/icon-left.png');
background-position: right;
}
&[data-direction="right"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/college-plan/icon-right.png');
background-position: left;
}
}
.college-header__text {
margin: 0;
padding: 0 10px;
font-size: 14px;
font-weight: 500;
color: #525C65;
line-height: 1;
}
.college-header__decorate {
display: block;
width: 39px;
height: 3px;
margin: 0 auto;
border-radius: 2px;
background: linear-gradient(90deg,rgba(0,153,255,1) 0%,rgba(55,117,239,1) 100%);
}
\ No newline at end of file
import React, { Component } from 'react';
import { http } from '@/utils';
import { HeaderBar } from "@/common";
import CollegeBanner from './banner';
import CollegeHeader from './header';
import './index.scss';
class CollegePage extends Component {
constructor(props) {
super(props);
this.state = {
sectionInfo: [
{
title: '系统赞助',
desc: '免费提供在线直播系统,支持电脑屏幕实时演示,以及视频回放、互动答疑。',
icon: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/college-plan/system.png',
},
{
title: '课程赞助 ',
desc: '免费开放相关课程的视频、课件、作业、考试、代码、项目、云平台(在线编译、在线批改)。',
icon: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/college-plan/content.png',
},
],
schoolList: [],
};
}
componentDidMount() {
this.fetchSchoolList();
document.title = `免费提供在线教学系统 助力全国高校在线教学 - 七月在线`
}
fetchSchoolList = () => {
const { schoolList } = this.state;
http.get(`${API['home']}/sys/school/list`).then(res => {
const { code, data } = res.data;
if(code === 200) {
this.setState({
schoolList: data.concat(schoolList),
});
}
});
}
toCollegeCourse = (id) => {
const { history } = this.props;
if(id) {
history.push(`/college/${id}`);
}
}
render() {
const { sectionInfo = [], schoolList = [] } = this.state;
return (
<>
<HeaderBar title={'助学计划'} arrow={true}/>
<CollegeBanner />
<div className="college-page__banner"></div>
<CollegeHeader
headerStyle={{
marginTop: '20px'
}}
title="助力高校在线教学计划"
/>
<p className="college-page__contact">免费入驻联系周先生:18910848502(微信同)</p>
{
sectionInfo.map(({title, desc, icon}, index) => (
<div className="college-page__section" key={index}>
<i className="section__icon" style={{'backgroundImage': `url(${icon})`}}></i>
<div className="section__body">
<h2 className="section__title">{title}</h2>
<p className="section__desc">{desc}</p>
</div>
</div>
))
}
<CollegeHeader
headerStyle={{
marginTop: '20px'
}}
isDecorate={false}
title="入驻院校"
/>
<div className="college-page__college">
{
schoolList.map(({id, name, logo}) => (
<div
className="college__item"
onClick={() => this.toCollegeCourse(id)}
key={id}
>
<i className="college__iamge" style={{'backgroundImage': `url(${logo})`}}></i>
<p className="college__name">{name}</p>
</div>
))
}
</div>
</>
)
}
}
export default CollegePage;
\ No newline at end of file
.college-page__contact {
margin: 5px 0 0;
font-size: 12px;
color: #0099FF;
text-align: center;
line-height: 22px;
}
.college-page__section {
margin: 0 15px 10px;
border: 1px solid #ECECEC;
border-radius: 1px;
.section__icon {
float: left;
width: 30px;
height: 34px;
margin: 13px 0 0 15px;
background-size: 100% auto;
background-position: center;
background-repeat: no-repeat;
}
.section__body {
margin-left: 60px;
padding: 8px 0;
}
.section__title {
margin: 0 0 4px;
font-size: 14px;
font-weight: 400;
color: #0099FF;
line-height: 1;
}
.section__desc {
margin: 0;
font-size: 12px;
color: #333;
line-height: 15px;
}
}
.college-page__college {
// display: flex;
// flex-wrap: wrap;
padding: 4px 10px 0;
.college__item {
// width: 166px;
margin: 0 5px 10px;
cursor: pointer;
}
.college__iamge {
display: block;
height: 60px;
border: 1px solid #ECECEC;
border-radius: 1px;
background-size: auto 95%;
background-position: center;
background-repeat: no-repeat;
}
.college__name {
margin: 6px 0 0;;
font-size: 12px;
color: #525C65;
text-align: center;
line-height: 16px;
}
}
\ No newline at end of file
import React, { PureComponent } from "react" import React, { PureComponent } from "react"
import './accountLogin.scss' import './accountLogin.scss'
import { Link } from "react-router-dom"; import { Link } from "react-router-dom"
import { withFormik, FastField, Form } from "formik"; import { withFormik, FastField, Form } from "formik"
import { compose } from 'redux'; import { compose } from 'redux'
import { accountLogin } from '@/store/userAction'; import { accountLogin } from '@/store/userAction'
import { connect } from "react-redux"; import { connect } from "react-redux"
import { isEmpty } from 'lodash' import { isEmpty } from 'lodash'
import { HeaderBar } from "@/common"; import { HeaderBar } from "@/common"
import Header from "../common/Header"; import Header from "../common/Header"
import Input from '../common/Input' import Input from '../common/Input'
import LoginButton from '../common/LoginButton' import LoginButton from '../common/LoginButton'
import PasswordInput from '../common/passwordInput' import PasswordInput from '../common/passwordInput'
import { Toast } from "antd-mobile"; import { Toast } from "antd-mobile"
class AccountLogin extends PureComponent { class AccountLogin extends PureComponent {
render() { render() {
const { const {
errors, errors,
values values
} = this.props } = this.props
return ( return (
<div className={'account-login'}> <div className={'account-login'}>
<HeaderBar arrow={true} title={'登录'}/> <HeaderBar arrow={true} title={'登录'}/>
<Header/> <Header/>
<Form className="login-info"> <Form className="login-info">
<FastField <FastField
name='account' name='account'
render={({field}) => ( render={({field}) => (
<Input <Input
{...field} {...field}
type={'text'} type={'text'}
placeholder={'手机/邮箱/昵称'} placeholder={'手机/邮箱/昵称'}
wrapperClass={'tel-input'} wrapperClass={'tel-input'}
icon={ icon={
<i className={'iconfont iconshouji'} <i className={'iconfont iconshouji'}
style={{fontSize: '22px', left: '10px'}} style={{fontSize: '22px', left: '10px'}}
/> />
} }
/> />
)} )}
/> />
<FastField <FastField
name='password' name='password'
render={({field}) => ( render={({field}) => (
<PasswordInput <PasswordInput
{...field} {...field}
autoComplete={'on'} autoComplete={'on'}
placeholder={'密码'} placeholder={'密码'}
icon={ icon={
<i className={'iconfont iconiconfront-74 lock-icon'}/> <i className={'iconfont iconiconfront-74 lock-icon'}/>
} }
/> />
)} )}
/> />
<LoginButton active={values.account && values.password && isEmpty(errors)}/> <LoginButton active={values.account && values.password && isEmpty(errors)}/>
<Link className={'forgot-password-btn'} to='/passport/forgot-password'>忘记密码</Link> <Link className={'forgot-password-btn'} to='/passport/forgot-password'>忘记密码</Link>
</Form> </Form>
</div> </div>
); )
} }
} }
const formikConfig = { const formikConfig = {
mapPropsToValues: () => ({ mapPropsToValues: () => ({
account: '', account: '',
password: '' password: ''
}), }),
handleSubmit(values, formikBag) { handleSubmit(values, formikBag) {
const {account: username, password} = values const {account: username, password} = values
const {props, props: {history}} = formikBag const {props, props: {history}} = formikBag
const from = props.location.state && props.location.state.from const from = props.location.state && props.location.state.from
props.accountLogin({ props.accountLogin({
username, password,redirect: from && window.location.origin + from.pathname + from.search + from.hash username, password, redirect: from && window.location.origin + from.pathname + from.search + from.hash
}).then(res => { }).then(res => {
if (res.hasError) { if (res.hasError) {
Toast.info(res.msg, 2, null, false) Toast.info(res.msg, 2, null, false)
} }
}) })
},
validate: values => {
const errors = {}
if (!values.account) {
errors.account = '账号不能为空'
} else if (!values.password) {
errors.password = '密码不能为空'
} }
return errors
}
} }
export default compose( export default compose(
connect( connect(
state => ({user: state.user}), state => ({user: state.user}),
{accountLogin} {accountLogin}
), ),
withFormik(formikConfig) withFormik(formikConfig)
)(AccountLogin) )(AccountLogin)
...@@ -12,6 +12,7 @@ import ForgotPasswordEmail from './forgotPasswordEmail' ...@@ -12,6 +12,7 @@ import ForgotPasswordEmail from './forgotPasswordEmail'
import { connect } from "react-redux" import { connect } from "react-redux"
import { compose } from "redux" import { compose } from "redux"
import { getParam } from "@/utils" import { getParam } from "@/utils"
import StudentRoot from './studentRoot';
import account from './icons/account.png' import account from './icons/account.png'
import qq from './icons/qq.png' import qq from './icons/qq.png'
...@@ -48,13 +49,13 @@ class Passport extends Component { ...@@ -48,13 +49,13 @@ class Passport extends Component {
{ {
logo: qq, logo: qq,
text: 'QQ', text: 'QQ',
url: `${API["passport-api"]}/mob/qqlogin?redirect_url=${encodeURIComponent(this.redirectURL)}`, url: `${API["passport-api"]}/m/login/qqLogin?redirect_url=${encodeURIComponent(this.redirectURL)}`,
id: 'qq' id: 'qq'
}, },
{ {
logo: sina, logo: sina,
text: '新浪', text: '新浪',
url: `${API['passport-api']}/mob/sinalogin?redirect_url=${encodeURIComponent(this.redirectURL)}`, url: `${API['passport-api']}/m/login/sinaLogin?redirect_url=${encodeURIComponent(this.redirectURL)}`,
id: 'sina' id: 'sina'
} }
] ]
...@@ -103,6 +104,7 @@ class Passport extends Component { ...@@ -103,6 +104,7 @@ class Passport extends Component {
from={'/passport'} from={'/passport'}
to={{...location, ...{pathname: '/passport/login'}}} to={{...location, ...{pathname: '/passport/login'}}}
/> />
<Route path={match.url + '/student-login'} component={StudentRoot}/>
<Route path={match.url + '/login'} <Route path={match.url + '/login'}
render={props => { render={props => {
return <Login {...props} loginWays={this.state.loginWays}/> return <Login {...props} loginWays={this.state.loginWays}/>
......
...@@ -43,7 +43,7 @@ class Login extends Component { ...@@ -43,7 +43,7 @@ class Login extends Component {
window.location.assign(`https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=${encodeURIComponent(redirectURI)}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`) window.location.assign(`https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx23dac6775ac82877&redirect_uri=${encodeURIComponent(redirectURI)}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`)
break; break;
case 'QQ': case 'QQ':
window.location.assign(`${API["passport-api"]}/mob/qqlogin?redirect_url=${encodeURIComponent(redirectURI)}`); window.location.assign(`${API["passport-api"]}/m/login/qqLogin?redirect_url=${encodeURIComponent(redirectURI)}`);
break; break;
default: default:
window.location.assign(item.url) window.location.assign(item.url)
...@@ -66,6 +66,11 @@ class Login extends Component { ...@@ -66,6 +66,11 @@ class Login extends Component {
} }
} }
toStudentRegister = () => {
const { history } = this.props;
history.push('/passport/student-login')
}
render() { render() {
const { const {
loginWays, loginWays,
...@@ -117,8 +122,12 @@ class Login extends Component { ...@@ -117,8 +122,12 @@ class Login extends Component {
onVerify={this.onVerify} onVerify={this.onVerify}
/> />
<LoginButton active={values.tel && values.veriCode && isEmpty(errors)}/> <LoginButton active={values.tel && values.veriCode && isEmpty(errors)}/>
{/* 助学计划 */}
<div className="student-root">
<a className="student-root__button" onClick={this.toStudentRegister}>助学计划</a>
</div>
</Form> </Form>
<LoginWays onClick={this.loginWaysClick} loginWays={loginWays}/> <LoginWays onClick={this.loginWaysClick} loginWays={loginWays}/>
</div> </div>
) )
......
...@@ -25,5 +25,15 @@ ...@@ -25,5 +25,15 @@
} }
.student-root {
padding-top: 18px;
text-align: right;
}
.student-root__button {
font-size: 15px;
color: #0099FF;
line-height: 1;
cursor: pointer;
}
} }
\ No newline at end of file
...@@ -69,7 +69,9 @@ const formikConfig = { ...@@ -69,7 +69,9 @@ const formikConfig = {
}, },
handleSubmit: (values, {props}) => { handleSubmit: (values, {props}) => {
let from = props.location.state && props.location.state.from || {pathname: '/'} const {location} = props
let from = location.state && location.state.records && location.state.records[location.state.records.length - 2] || {pathname: '/'}
if (from.pathname.includes('forgot-password')) { if (from.pathname.includes('forgot-password')) {
forgotPasswordReset(values, props) forgotPasswordReset(values, props)
} else { } else {
......
.student-form {
margin-top: -27px;
padding: 0 35px;
.input-with-country-codes {
margin-bottom: 15px;
}
}
.student-form__code {
margin: 0 0 15px;
&.input-wrapper {
width: 100%;
}
}
.student-form__item {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.student-form__label {
width: 44px;
font-size: 15px;
color: 333;
}
.student-form__input {
flex: 1;
height: 46px;
padding: 0 15px;
border: 1px solid #ccc;
border-radius: 3px;
box-sizing: border-box;
font-size: 15px;
color: #999;
}
.student-form__footer {
position: relative;
margin-top: 35px;
}
.student-form__tip {
position: absolute;
top: -25px;
margin: 0;
padding-left: 60px;
font-size: 12px;
color: #FF1717;
line-height: 1;
}
.student-form__submit {
width: 100%;
height: 44px;
padding: 0;
border-style: none;
border-radius: 3px;
font-size: 18px;
color: #fff;
background-color: #0099FF;
&:disabled {
background-color: #ccc;
}
}
.student-select {
position: relative;
flex: 1;
height: 46px;
input {
width: 100%;
height: 100%;
padding: 0 15px;
border: 1px solid #ccc;
border-radius: 3px;
box-sizing: border-box;
font-size: 15px;
color: #999;
&.active {
border-radius: 3px 3px 0 0;
}
}
}
.student-select__list {
position: absolute;
top: 45px;
width: 100%;
border: 1px solid #ccc;
border-radius: 0 0 3px 3px;
box-sizing: border-box;
background-color: #fff;
z-index: 99;
}
.student-select__option {
padding-left: 15px;
font-size: 14px;
color: #999;
line-height: 32px;
&:hover {
color: #0099FF;
}
}
\ No newline at end of file
import React, {Component} from 'react' import React, {Component} from 'react'
import {http, getParam, SendMessageToApp} from '@/utils' import {http, getParam, browser, SendMessageToApp} from '@/utils'
import PythonDes from './pythomDes' import PythonDes from './pythomDes'
import PythonStudy from './pythonStudy' import PythonStudy from './pythonStudy'
import {connect} from "react-redux" import {connect} from "react-redux"
...@@ -19,7 +19,8 @@ class Python extends Component { ...@@ -19,7 +19,8 @@ class Python extends Component {
this.state = { this.state = {
isPay: '', isPay: '',
userInfoList: [], userInfoList: [],
isAppUpdate: false isAppUpdate: false,
backwardVersion: false, // 默认是新版本
} }
} }
...@@ -60,10 +61,12 @@ class Python extends Component { ...@@ -60,10 +61,12 @@ class Python extends Component {
this.setState({ this.setState({
isAppUpdate: true isAppUpdate: true
}) })
this.fetchCourseInfo();
} }
this.props.setCurrentUser(this.transformUser(this.state.userInfoList)) this.props.setCurrentUser(this.transformUser(this.state.userInfoList));
} }
transformUser = res => { transformUser = res => {
let payload let payload
...@@ -89,19 +92,53 @@ class Python extends Component { ...@@ -89,19 +92,53 @@ class Python extends Component {
http.get(`${API.home}/m/course/detail/${id}`).then((res) => { http.get(`${API.home}/m/course/detail/${id}`).then((res) => {
const {data, code} = res.data const {data, code} = res.data
if (code === 200) { if (code === 200) {
this.setState({ let version = getParam('version')
isPay: data.course_info.is_pay if(version) {
}) version = version.replace(/\./g, '').slice(0, 3)
if(browser.isAndroidApp && version < 453) { // 安卓的低版本
this.setState({
backwardVersion: true,
isPay: 0,
})
}else if(browser.isIOSApp && version < 380) { // ISO的低版本
this.setState({
backwardVersion: true,
isPay: 0,
})
}else{ // 安卓/IOS 的高版本
if(data.course_info.is_pay === 1) { // 在APP内未登录-去登陆-登录后还显示此页;如果是已购买的用户 就需要跳转到 APP已购买的原生页面
SendMessageToApp('toSyllabusChapter', id); // 跳转到APP的已购买详情页 id 是课程ID
return;
}
this.setState({
backwardVersion: false,
isPay: data.course_info.is_pay
})
}
} else {
this.setState({
backwardVersion: false,
isPay: data.course_info.is_pay
})
}
} }
}) })
} }
render() { render() {
const {isPay, isAppUpdate} = this.state const {isPay, isAppUpdate, backwardVersion} = this.state;
// 旧版本 无论购买未购买 都跳转到 未购买的详情页; 如果是已购买就提示更新APP
return ( return (
<div> <div>
{ {
isPay === 0 && <PythonDes history={this.props.history} isAppUpdate={isAppUpdate}></PythonDes> isPay === 0 && (
<PythonDes
backwardVersion={backwardVersion}
history={this.props.history}
isAppUpdate={isAppUpdate}
isPay={isPay}
/>
)
} }
{ {
(isPay === 1 && !getParam('version')) && <PythonStudy isAppUpdate={isAppUpdate}/> (isPay === 1 && !getParam('version')) && <PythonStudy isAppUpdate={isAppUpdate}/>
......
...@@ -8,7 +8,7 @@ export default class Description extends Component { ...@@ -8,7 +8,7 @@ export default class Description extends Component {
<img className={'left'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/left.png" alt=""/> <img className={'left'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/left.png" alt=""/>
<img className={'right'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/right.png" alt=""/> <img className={'right'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/right.png" alt=""/>
<p className={'title'}> / / / </p> <p className={'title'}> / / / </p>
<p className={'sub__title'}>对话式交互教学+课后实操,20节课全面掌握Python基础语法</p> <p className={'sub__title'}>对话式交互教学+课后实操,17节课全面掌握Python基础语法</p>
<img src={'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/diannao.png'} /> <img src={'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/diannao.png'} />
{ {
this.props.list.map((item, index)=>{ this.props.list.map((item, index)=>{
......
...@@ -3,18 +3,41 @@ import './index.scss' ...@@ -3,18 +3,41 @@ import './index.scss'
export default class Experience extends Component { export default class Experience extends Component {
render() { render() {
const { isOnline, tryLearn } = this.props;
return ( return (
<div className={'experience_container'}> <div className={'experience_container'}>
<p className={'title'}> / / / </p> <p className={'title'}> / / / </p>
<div className={'experience'}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/L%402x.png" alt=""/> {
<div> isOnline
<p>限时福利免费试学</p> ? (
<p>开始颠覆你想象的学习</p> <>
</div> <div className={'experience'}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/r%402x.png" alt=""/> <img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/L%402x.png" alt=""/>
</div> <div>
<div className={'btn'} onClick={this.props.tryLearn}>立即体验</div> <p>限时福利免费试学</p>
<p>开始颠覆你想象的学习</p>
</div>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/r%402x.png" alt=""/>
</div>
<div className={'btn'} onClick={tryLearn}>立即体验</div>
</>
)
: (
<>
<div className={'experience'}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/L%402x.png" alt=""/>
<div>
<p>上架后可免费试学</p>
<p>体验颠覆你想象的学习</p>
</div>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/r%402x.png" alt=""/>
</div>
<div className={'btn btn--online'}>即将上架敬请期待</div>
</>
)
}
</div> </div>
) )
} }
......
...@@ -31,14 +31,22 @@ ...@@ -31,14 +31,22 @@
.btn { .btn {
width: 150px; width: 150px;
height: 36px; height: 36px;
background: rgba(0, 153, 255, 1); margin: 0 auto;
box-shadow: 0px 6px 12px 0px rgba(0, 153, 255, 0.06);
border-radius: 18px; border-radius: 18px;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
color: rgba(255, 255, 255, 1); color: rgba(255, 255, 255, 1);
line-height: 36px;
text-align: center; text-align: center;
margin: 0 auto; line-height: 36px;
background: rgba(0, 153, 255, 1);
box-shadow: 0px 6px 12px 0px rgba(0, 153, 255, 0.06);
}
.btn--online {
width: 200px;
font-size: 15px;
color: #fff;
letter-spacing: 4px;
background-color: rgba(82,92,101,.6);
} }
} }
...@@ -16,7 +16,7 @@ export default class Progream extends Component { ...@@ -16,7 +16,7 @@ export default class Progream extends Component {
q: '学习过程中遇到了困难怎么办?', q: '学习过程中遇到了困难怎么办?',
a: '我们为学员配备了专门的助教,有问题随时可以咨询助教老师。' a: '我们为学员配备了专门的助教,有问题随时可以咨询助教老师。'
},{ },{
q: '课程学习周期是多久?', q: '需要自己安装代码运行环境吗?',
a: '在平台上学习不需要安装任何环境,该课程包含的知识点实操以及课后实操都可以在平台上完成。' a: '在平台上学习不需要安装任何环境,该课程包含的知识点实操以及课后实操都可以在平台上完成。'
} }
] ]
......
...@@ -2,13 +2,34 @@ import React, { Component } from 'react' ...@@ -2,13 +2,34 @@ import React, { Component } from 'react'
import './index.scss' import './index.scss'
export default class Study extends Component { export default class Study extends Component {
Change = (data) => {
let cn = ["一", "二", "三", "四", "五", "六", "七", "八", "九", '十'];
let newStr = ''
let str = data.toString()
let ci = Number(str) % 10
let cs = Math.floor(Number(str) / 10)
let cv = ''
if (str.length > 1) {
if(cs==1){
cv = ci >= 1 ? cn[9] + cn[ci - 1] : cn[9]
} else {
cv = ci > 1 ? cn[cs - 1] + cn[9] + cn[ci - 1] : cn[cs - 1] + cn[9]
}
} else {
cv = cn[ci - 1]
}
newStr = str.replace(str, cv)
return newStr;
}
render() { render() {
return ( return (
<div className={'study__container'}> <div className={'study__container'}>
<img className={'learn_left'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/learn_left.png" alt=""/> <img className={'learn_left'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/learn_left.png" alt=""/>
<img className={'learn_bottom'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/learn_bottom.png" alt=""/> <img className={'learn_bottom'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/learn_bottom.png" alt=""/>
<p className={'title'}> / / / </p> <p className={'title'}> / / / </p>
<p className={'sub__title'}>20节课堂教学,带你掌握Python技术入门知识</p> <p className={'sub__title'}>17节课堂教学,带你掌握Python技术入门知识</p>
<div className={'step__container'}> <div className={'step__container'}>
<div className={'item__container'}> <div className={'item__container'}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/wanzheng.png" alt=""/> <img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/wanzheng.png" alt=""/>
...@@ -37,13 +58,14 @@ export default class Study extends Component { ...@@ -37,13 +58,14 @@ export default class Study extends Component {
this.props.syllabus.map((item, index)=>{ this.props.syllabus.map((item, index)=>{
return ( return (
<div className={'item__container'} key={index}> <div className={'item__container'} key={index}>
<div className={'item__title'}>{item.name}</div> <div className={'item__title'}>{
'第' + this.Change(index + 1) + '阶段 ' +item.name}</div>
{ {
item.lessons.map((item, index)=>{ item.lessons.map((item, index)=>{
return ( return (
<div className={'item__content'} key={index}> <div className={'item__content'} key={index}>
<div className={'content order_number number_center'}>{item.number}</div> <div className={'content order_number number_center'}>{item.number}</div>
<div className={'content chapter'}>{item.number}</div> <div className={'content chapter'}>{item.name}</div>
<div className={'content points'}>{item.info.name}</div> <div className={'content points'}>{item.info.name}</div>
</div> </div>
) )
......
...@@ -8,23 +8,23 @@ export default class Team extends Component { ...@@ -8,23 +8,23 @@ export default class Team extends Component {
teacherList: [ teacherList: [
{ {
avatar: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/teacher1.png', avatar: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/teacher1.png',
name: 'A老师', name: '陈博士',
des: '七月在线AI Lab负责人兼科学家。历任浪潮集团数七月在线AI Lab负责人兼科学家。历任浪潮集团数七月在线AI Lab负责人兼科学家。历任浪潮集团数据科学家,国家电网人工智能行业应用方向团队负责人。参与过一国家863项目,且曾主持一山东省自主创新及成果转化专项,发明专利十余项,专业论文十余年哈哈塑料袋科技发牢骚' des: '七月在线AI Lab负责人兼科学家。历任浪潮集团数据科学家,国家电网人工智能行业应用方向团队负责人。参与过一国家863项目,且曾主持一山东省自主创新及成果转化专项,发明专利十余项,专业论文十余篇。'
}, },
{ {
avatar: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/teacher2.png', avatar: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/teacher2.png',
name: 'A老师', name: '老师',
des: '七月在线AI Lab负责人兼科学家。历任浪潮集团数据科学家,' des: '10多年开发经验,先后任职国内知名互联网企业,从事人工智能方向的实施,擅长全栈开发,将机器学习/深度学习结合到实际生产运营中。'
}, },
{ {
avatar: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/teacher3.png', avatar: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/teacher3.png',
name: 'A老师', name: '老师',
des: '七月在线AI Lab负责人兼科学家。历任浪潮集团数据科学家,' des: '计算机专业毕业,多年开发经验,熟悉 Python,熟悉 linux 环境下系统编程,具有多年的 Web 后端开发经验,授课思路清晰明了,通俗易懂,幽默风趣的讲课方式将枯燥的知识以通俗的方式展现,深受学生好评。'
}, },
{ {
avatar: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/teacher4.png', avatar: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/teacher4.png',
name: 'A老师', name: '珊酱',
des: '七月在线AI Lab负责人兼科学家。历任浪潮集团数据科学家,国家电网人工智能行业应用方向团队负责人。参与过一国家863项目,且曾主持一山东省自主创新及成果转化专项,发明专利十余项,专业论文十余年哈哈塑料袋科技发牢骚' des: '班主任的工作是一项非常辛苦和琐碎的工作,不付出艰辛的劳动和辛苦的汗水是不会有收获的。历经数万名学员的一对一服务,始终坚持给学员做到最好的服务和最严格的要求,学员的点滴进步和成长就是我最大的期望!'
} }
] ]
} }
......
...@@ -35,12 +35,12 @@ export default class Test extends Component { ...@@ -35,12 +35,12 @@ export default class Test extends Component {
<div className={'table_body'}> <div className={'table_body'}>
{ {
this.props.practice.map((item, index)=>{ this.props.practice.map((item, index)=>{
return <div key={index}> return <div className="stage-item" key={index}>
<div className='stage'>{`第${this.Change(item.stage)}阶段 ${item.name}`}</div> <div className='stage'>{`第${this.Change(item.stage)}阶段 ${item.name}`}</div>
{ {
item.questions.map((question, index)=>{ item.questions.map((question, index)=>{
return <div key={index} className={'line'}> return <div key={index} className={'line'}>
<span>{index}</span> <span>{question.number}</span>
<div className={'test_name'}> <div className={'test_name'}>
<img src={question.icon} alt=""/> <img src={question.icon} alt=""/>
<p>{question.name}</p> <p>{question.name}</p>
......
...@@ -49,6 +49,10 @@ ...@@ -49,6 +49,10 @@
.table_body { .table_body {
background: #34AFFF; background: #34AFFF;
.stage-item {
border-bottom: 1px solid #0099FF;
}
.stage { .stage {
height: 38px; height: 38px;
font-size: 14px; font-size: 14px;
...@@ -59,6 +63,7 @@ ...@@ -59,6 +63,7 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.line { .line {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -94,7 +99,6 @@ ...@@ -94,7 +99,6 @@
.table_bottom { .table_bottom {
height: 36px; height: 36px;
background: #3DB1FF; background: #3DB1FF;
border-top: 1px solid #0099FF;
div { div {
display: flex; display: flex;
justify-content: center; justify-content: center;
......
...@@ -74,8 +74,8 @@ class PythonDes extends Component { ...@@ -74,8 +74,8 @@ class PythonDes extends Component {
}, },
{ {
url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/rumen.png', url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/rumen.png',
title: '20天零基础入门', title: '17天零基础入门',
subTitle: '降低学习门槛,20天入门人工智能' subTitle: '降低学习门槛,17天入门人工智能'
}, },
], ],
worryList: [ worryList: [
...@@ -87,7 +87,7 @@ class PythonDes extends Component { ...@@ -87,7 +87,7 @@ class PythonDes extends Component {
{ {
url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/xuexi.png', url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/xuexi.png',
title: '想学习,没有坚持下来', title: '想学习,没有坚持下来',
subTitle: '以故事性的方式编写学习内容, 把生硬的知识点有趣化。精美的图片+幽默的文字+代码编写让你越学越学。' subTitle: '以故事性的方式编写学习内容, 把生硬的知识点有趣化。精美的图片+幽默的文字+代码编写让你越学越学。'
}, },
{ {
url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/zhishidian.png', url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/zhishidian.png',
...@@ -95,6 +95,8 @@ class PythonDes extends Component { ...@@ -95,6 +95,8 @@ class PythonDes extends Component {
subTitle: '每节课的知识点都设有代码编写部分,每节课课后都有课后实操。有多次代码编写练习的机会,助你真正学以致用。' subTitle: '每节课的知识点都设有代码编写部分,每节课课后都有课后实操。有多次代码编写练习的机会,助你真正学以致用。'
}, },
], ],
payMoney: 0,
isOnline: true, //课程是否上架
} }
} }
...@@ -119,6 +121,7 @@ class PythonDes extends Component { ...@@ -119,6 +121,7 @@ class PythonDes extends Component {
} }
toLearn = () => { toLearn = () => {
const {backwardVersion} = this.props;
http.post(`${API['home']}/m/it/user/trialCourse`, {course_id: getParam('id')}).then((res) => { http.post(`${API['home']}/m/it/user/trialCourse`, {course_id: getParam('id')}).then((res) => {
const {code, msg} = res.data const {code, msg} = res.data
if (code == 200) { if (code == 200) {
...@@ -127,7 +130,11 @@ class PythonDes extends Component { ...@@ -127,7 +130,11 @@ class PythonDes extends Component {
toApp: true toApp: true
}) })
} else { // APP } else { // APP
SendMessageToApp("toLearn") if(backwardVersion) {
Toast.info('当前版本不支持该课程模式,请升级到最新版本或前往PC端体验', 2)
} else {
SendMessageToApp("toLearn", getParam('id'))
}
} }
} else { } else {
Toast.info(msg, 2) Toast.info(msg, 2)
...@@ -142,6 +149,7 @@ class PythonDes extends Component { ...@@ -142,6 +149,7 @@ class PythonDes extends Component {
} }
toDetail = () => { toDetail = () => {
const {backwardVersion} = this.props;
const id = getParam('id') const id = getParam('id')
if (!getParam('version')) { // H5 if (!getParam('version')) { // H5
http.get(`${API['base-api']}/m/cart/addtopreorder/[${id}]`).then((res) => { http.get(`${API['base-api']}/m/cart/addtopreorder/[${id}]`).then((res) => {
...@@ -152,7 +160,16 @@ class PythonDes extends Component { ...@@ -152,7 +160,16 @@ class PythonDes extends Component {
} }
}) })
} else { // APP } else { // APP
SendMessageToApp('toPay', id) if(backwardVersion) {
Toast.info('当前版本不支持该课程模式,请升级到最新版本或前往PC端购买', 2);
let onlyoneUse = setTimeout(() => {
clearTimeout(onlyoneUse);
onlyoneUse = null;
SendMessageToApp('toPay', id)
}, 2000);
} else {
SendMessageToApp('toPay', id)
}
} }
} }
...@@ -202,6 +219,7 @@ class PythonDes extends Component { ...@@ -202,6 +219,7 @@ class PythonDes extends Component {
allSyllabus: data.syllabus, allSyllabus: data.syllabus,
practice: data.practice.slice(0, 2), practice: data.practice.slice(0, 2),
allPractice: data.practice, allPractice: data.practice,
payMoney: data.course_info.price1,
}) })
} else { } else {
Toast.info(msg) Toast.info(msg)
...@@ -211,6 +229,11 @@ class PythonDes extends Component { ...@@ -211,6 +229,11 @@ class PythonDes extends Component {
componentDidMount() { componentDidMount() {
this.getStatus() this.getStatus()
const {backwardVersion, isPay} = this.props;
if(backwardVersion && isPay === 1) {
Toast.info('当前版本不支持该课程模式,请升级到最新版本或前往PC端学习', 2);
}
} }
...@@ -223,7 +246,18 @@ class PythonDes extends Component { ...@@ -223,7 +246,18 @@ class PythonDes extends Component {
} }
render() { render() {
const {defineList, desList, worryList, syllabus, practice, allSyllabusShow, allPracticeShow, toApp} = this.state const {
defineList,
desList,
worryList,
syllabus,
practice,
allSyllabusShow,
allPracticeShow,
toApp,
payMoney,
isOnline
} = this.state
return ( return (
<div className={'python__des'}> <div className={'python__des'}>
<div className={'des__start'}></div> <div className={'des__start'}></div>
...@@ -240,31 +274,64 @@ class PythonDes extends Component { ...@@ -240,31 +274,64 @@ class PythonDes extends Component {
} }
</div> </div>
<div className={'course__introduce'}></div> <div className={'course__introduce'}></div>
<div className={'bottom__btn_group'}> {
<div className={'course__price'}> isOnline
<div className={'money'}>199<span style={{fontSize: '18px'}}></span></div> ? (
<div className={'discount'}> <div className={'bottom__btn_group'}>
限时特惠 <div className={'course__price'}>
<div className={'triangle'}></div> <div className={'money'}>{payMoney}<span style={{fontSize: '18px'}}></span></div>
<div className={'discount'}>
限时特惠
<div className={'triangle'}></div>
</div>
</div>
<div className={'btn__group'}>
<div className={'try__study'} onClick={this.tryLearn}>免费试学</div>
<div className={'sign__now'} onClick={this.signUp}>立即报名</div>
</div>
</div> </div>
</div> )
: (
<div className="bottom__btn_group">
<p className="online__label">Python人工智能</p>
<button className="online__button">即将上架 敬请期待</button>
</div>
)
}
{/* 课程介绍 */}
<Description list={desList} />
<div className={'btn__group'}>
<div className={'try__study'} onClick={this.tryLearn}>免费试学</div>
<div className={'sign__now'} onClick={this.signUp}>立即报名</div>
</div>
</div>
<Description list={desList}></Description>
<NoWorry list={worryList}></NoWorry> <NoWorry list={worryList}></NoWorry>
<Study syllabus={syllabus} allSyllabusShow={allSyllabusShow} show={this.showAll} <Study syllabus={syllabus} allSyllabusShow={allSyllabusShow} show={this.showAll}
hide={this.hideSome}></Study> hide={this.hideSome}></Study>
<Test practice={practice} allPracticeShow={allPracticeShow} show={this.showAll}
hide={this.hideSome}></Test> {/* 课后实操 */}
<Test
practice={practice}
allPracticeShow={allPracticeShow}
show={this.showAll}
hide={this.hideSome}
/>
<Team/> <Team/>
<Experience tryLearn={this.tryLearn}/>
<img style={{display: 'block', width: '100%', height: '8px'}} {/* 试学体验 */}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/changjian.png" alt=""/> <Experience tryLearn={this.tryLearn} isOnline={isOnline} />
<Progream/> <img
style={{
display: 'block',
width: '100%',
height: '8px'
}}
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/changjian.png"
alt=""
/>
{/* 常见问题 */}
<Progream />
{ {
toApp && (<Mask type={1} closePop={this.closePop}/>) toApp && (<Mask type={1} closePop={this.closePop}/>)
} }
......
...@@ -86,6 +86,24 @@ ...@@ -86,6 +86,24 @@
padding: 0 14px; padding: 0 14px;
background: #fff; background: #fff;
.online__label {
font-size: 18px;
font-weight: 600;
color: #525C65;
}
.online__button {
width: 160px;
height: 37px;
border-style: none;
border-radius: 19px;
font-size: 15px;
font-weight: 600;
color: #fff;
background-color: rgba(82,92,101,.6);
outline: none;
}
.course__price { .course__price {
width: 100px; width: 100px;
font-size: 24px; font-size: 24px;
......
...@@ -59,9 +59,34 @@ html:not([data-scale]) .am-accordion.python-study__stage .am-accordion-item .am- ...@@ -59,9 +59,34 @@ html:not([data-scale]) .am-accordion.python-study__stage .am-accordion-item .am-
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
position: relative;
height: 55px; height: 55px;
padding: 0 12px; padding: 0 12px;
background-color: #1A9BFC; background-color: #1A9BFC;
&::after {
content: '';
position: absolute;
left: -60px;
top: 0;
width: 146px;
height: 100%;
background-repeat: no-repeat;
background-size: 100% auto;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/pythonCourse/pc/python-title-bg-1.png');
}
&::before {
content: '';
position: absolute;
right: -60px;
bottom: -20px;
width: 106px;
height: 100%;
background-repeat: no-repeat;
background-size: 100% auto;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/pythonCourse/pc/python-title-bg-0.png');
}
} }
.python-study__course-name { .python-study__course-name {
......
...@@ -83,23 +83,15 @@ class PythonClass extends Component { ...@@ -83,23 +83,15 @@ class PythonClass extends Component {
handleToSend = (params) => { handleToSend = (params) => {
const { history } = this.props; const { history } = this.props;
const { isShare, entryMode } = this.state; const { isShare } = this.state;
if(browser.isWeixin) { if(browser.isWeixin) {
history.push(`/pythonShare?id=${getParam('id')}&type=${getParam('type')}&ques=${getParam('ques')}&origin=python`); history.push(`/pythonShare?id=${getParam('id')}&type=${getParam('type')}&ques=${getParam('ques')}&origin=python`);
this.setState({ this.setState({
isGuide: true isGuide: true
}); });
let title = '';
let labelName = this.formatTitle(params);
if(entryMode !== 0 && !isShare) {
title = `我在${params.course_name}${labelName}遇到了困难`;
}
if(entryMode !== 0 && isShare) {
title = `我已在【${params.course_name}】上运行了行代码了${params.code_lines}`
}
wxShare({ wxShare({
title, title: isShare? `我已在【${params.course_name}】上运行了行代码了${params.code_lines}` : `我在${params.course_name}${this.formatTitle(params)}遇到了困难`,
desc: labelName, desc: this.formatTitle(params),
link: encodeURI(location.href), link: encodeURI(location.href),
imgUrl: params.course_img, imgUrl: params.course_img,
}); });
...@@ -155,7 +147,7 @@ class PythonClass extends Component { ...@@ -155,7 +147,7 @@ class PythonClass extends Component {
data={data} data={data}
labelName={this.formatTitle(data)} labelName={this.formatTitle(data)}
handleToExecute={this.handleToExecute} handleToExecute={this.handleToExecute}
handleToSend={this.handleToSend} handleToSend={() => this.handleToSend(data)}
copyToSuccess={this.copyToSuccess} copyToSuccess={this.copyToSuccess}
handleToHide={this.handleToHide} handleToHide={this.handleToHide}
/> />
...@@ -203,7 +195,7 @@ function PythonContent(props) { ...@@ -203,7 +195,7 @@ function PythonContent(props) {
<div className="python-popup" onClick={handleToHide}> <div className="python-popup" onClick={handleToHide}>
<div className="python-header"> <div className="python-header">
<p className="python-wechat__title">请点击右上角分享</p> <p className="python-wechat__title">请点击右上角分享</p>
<i className="iconfont iconyindao"></i> <i className="iconfont"></i>
</div> </div>
</div> </div>
} }
......
...@@ -11,22 +11,26 @@ ...@@ -11,22 +11,26 @@
.python-header { .python-header {
position: relative; position: relative;
height: 100px; height: 100px;
padding-top: 34px; padding-top: 36px;
box-sizing: border-box; box-sizing: border-box;
.iconfont { .iconfont {
position: absolute; position: absolute;
top: -6px; top: 10px;
right: 40px; right: 40px;
font-size: 38px; font-size: 38px;
color: #fff; color: #fff;
width: 50px;
height: 38px;
background: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/pythonCourse/h5/share_arrow.png') center center no-repeat;
background-size: 100% 100%;
} }
} }
.python-wechat__title { .python-wechat__title {
margin: 0; margin: 0;
font-size: 17px; font-size: 17px;
color: #FCFF1D; color: #FFF;
text-align: center; text-align: center;
line-height: 1; line-height: 1;
} }
...@@ -172,7 +176,7 @@ ...@@ -172,7 +176,7 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: rgba(0, 0, 0, .3); background-color: rgba(0, 0, 0, .6);
z-index: 99; z-index: 99;
} }
......
...@@ -149,6 +149,7 @@ class CampTest extends Component { ...@@ -149,6 +149,7 @@ class CampTest extends Component {
data.answer_record = this.answerList; data.answer_record = this.answerList;
http.post(`${API.home}/m/aist/submit`, data).then((res) => { http.post(`${API.home}/m/aist/submit`, data).then((res) => {
if(res.data.code === 200) { if(res.data.code === 200) {
this.body = document.getElementsByTagName('body')[0];
this.body.style.position = 'static'; this.body.style.position = 'static';
this.props.history.push(`/campResolve?keshi_id=${this.keshi_id}&qid=${this.qid}`, {from: this.props.location.state.from}) this.props.history.push(`/campResolve?keshi_id=${this.keshi_id}&qid=${this.qid}`, {from: this.props.location.state.from})
}else{ }else{
......
...@@ -13,7 +13,6 @@ import { Modal } from "antd-mobile" ...@@ -13,7 +13,6 @@ import { Modal } from "antd-mobile"
import { Loading } from '@/common' import { Loading } from '@/common'
import { connect } from "react-redux" import { connect } from "react-redux"
import jsCookie from 'js-cookie' import jsCookie from 'js-cookie'
import io from 'socket.io-client'
import Single from "@/components/detail/single"; import Single from "@/components/detail/single";
import SingleSuccess from "../detail/single/singleSuccess"; import SingleSuccess from "../detail/single/singleSuccess";
import './CustomPlayButton' import './CustomPlayButton'
...@@ -83,8 +82,6 @@ class Video extends Component { ...@@ -83,8 +82,6 @@ class Video extends Component {
isCurrentVideoFirstPlay = true isCurrentVideoFirstPlay = true
WATCHTIME = "watch_time"
COUNTSCHEDULE = "count_schedule"
RECENTLEARN = "recent_learn" RECENTLEARN = "recent_learn"
state = { state = {
...@@ -136,7 +133,6 @@ class Video extends Component { ...@@ -136,7 +133,6 @@ class Video extends Component {
this.token = jsCookie.get('token') this.token = jsCookie.get('token')
this.getVideoList() this.getVideoList()
this.getDatumCatalog() this.getDatumCatalog()
this.setupRecord()
} }
// 直接购买 // 直接购买
...@@ -341,40 +337,6 @@ class Video extends Component { ...@@ -341,40 +337,6 @@ class Video extends Component {
}) })
} }
setupRecord = () => {
this.recordSocket = io(API.record, {
transports: ['websocket'],
forceNew: true
})
// this.recordSocket = io(API.record)
// this.recordSocket.on('seek', time => {
// this.player.currentTime(time)
// })
// 开启定时器 每5秒发送一次学习记录 --删除
this.recordTimer = setInterval(() => {
this.sendRecord()
}, 5000)
}
// 发送学习记录
sendRecord = () => {
if (this.recordSocket && this.player) {
this.recordSocket.emit('addRecord', this.recordUserInfo())
}
}
// 返回学习记录的数据
recordUserInfo = () => {
let {uid} = this.props.user.data
return {
uid,
course_id: this.courseID,
video_id: this.state.videoList[this.state.activeIndex]['id'],
video_time: parseInt(this.player.currentTime()),
plat: 5
}
}
// 9502 初始化 监听事件 // 9502 初始化 监听事件
setupWS = () => { setupWS = () => {
this.ws = new WebSocket(API["process-api"]); this.ws = new WebSocket(API["process-api"]);
...@@ -524,9 +486,6 @@ class Video extends Component { ...@@ -524,9 +486,6 @@ class Video extends Component {
} }
}) })
this.player.addChild('CustomPlayButtonCover') this.player.addChild('CustomPlayButtonCover')
this.player.on('ready', () => {
this.recordSocket.emit('load', this.recordUserInfo())
})
this.player.on('play', () => { this.player.on('play', () => {
const {videoList, activeIndex, vCourseId, course = {}} = this.state const {videoList, activeIndex, vCourseId, course = {}} = this.state
// 当视频播放时 看是否是第一次播放(初次进入页面 刷新页面 切换视频 都是第一次播放 需要获取上次的播放时间) // 当视频播放时 看是否是第一次播放(初次进入页面 刷新页面 切换视频 都是第一次播放 需要获取上次的播放时间)
...@@ -566,9 +525,6 @@ class Video extends Component { ...@@ -566,9 +525,6 @@ class Video extends Component {
clearInterval(this.timer); clearInterval(this.timer);
this.timer = null; this.timer = null;
}) })
this.player.on('seeked', () => {
this.sendRecord()
})
} }
sendLastRecord = () => { sendLastRecord = () => {
...@@ -895,6 +851,7 @@ class Video extends Component { ...@@ -895,6 +851,7 @@ class Video extends Component {
activeIndex={this.state.activeIndex} activeIndex={this.state.activeIndex}
selectVideo={this.selectVideo} selectVideo={this.selectVideo}
videoCatalog={videoList} videoCatalog={videoList}
isAist={course.is_aist}
{...props} {...props}
/> />
); );
......
...@@ -34,7 +34,8 @@ class VideoCatalog extends Component { ...@@ -34,7 +34,8 @@ class VideoCatalog extends Component {
)}/> )}/>
</div> </div>
{ {
(item.practice && item.practice.qid) this.props.isAist ? (
(item.practice && item.practice.qid)
? <Link to={{ ? <Link to={{
pathname: item.practice.is_tested ? '/campResolve' : '/campTest', pathname: item.practice.is_tested ? '/campResolve' : '/campTest',
search: `?keshi_id=${item.id}&qid=${item.practice.qid}`, search: `?keshi_id=${item.id}&qid=${item.practice.qid}`,
...@@ -46,6 +47,22 @@ class VideoCatalog extends Component { ...@@ -46,6 +47,22 @@ class VideoCatalog extends Component {
</div> </div>
</Link> </Link>
: null : null
) : (
item.practice_common.map((commonItem, index) => {
return (
<Link to={{
pathname: commonItem.is_tested ? '/campResolve' : '/campTest',
search: `?keshi_id=${item.id}&qid=${commonItem.qid}`,
state: {from: `/play/video${window.location.search}`}
}} key={index}>
<div className="exercise">
课后练习:{commonItem.title}
<i className={classnames('iconfont',!item.video_auth ? 'iconiconfront-74' : commonItem.is_tested ? 'iconiconfront-3' : '')}/>
</div>
</Link>
)
})
)
} }
</li> </li>
) )
......
...@@ -33,11 +33,16 @@ ...@@ -33,11 +33,16 @@
} }
} }
a:last-child {
.exercise {
margin-bottom: 15px;
}
}
.exercise { .exercise {
padding-left: 15px; padding-left: 15px;
height: 35px; height: 35px;
background: #F5FBFF; background: #F5FBFF;
margin-bottom: 15px;
line-height: 35px; line-height: 35px;
font-size: $font_12; font-size: $font_12;
color: #000; color: #000;
...@@ -52,12 +57,12 @@ ...@@ -52,12 +57,12 @@
.title { .title {
display: inline-block; display: inline-block;
width: 50%; width: 66%;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
font-size: $font_14; font-size: $font_14;
margin-right: 26px; margin-right: 12px;
} }
.duration { .duration {
......
import React from 'react'
import WxErrImage from '@assets/image/wx_error.png'
import './wxerr.scss'
const WxErr = () => {
return (
<div className={'wxerr'}>
<img src={WxErrImage} alt=''/>
<p className="openLink" style={{
fontSize: `16px`,
marginTop: `40px`
}}>请在微信客户端打开链接</p>
</div>
)
}
export default WxErr
.wxerr{
margin-top: 40px;
display: flex;
flex-flow: column;
align-items: center;
.openLink{
font-size: 16px;
margin-top:40px;
}
}
...@@ -4,7 +4,7 @@ import jsCookie from 'js-cookie' ...@@ -4,7 +4,7 @@ import jsCookie from 'js-cookie'
const accountLogin = user => dispatch => { const accountLogin = user => dispatch => {
return http.post(`${API['passport-api']}/user_login`, { return http.post(`${API['passport-api']}/m/login/accountLogin`, {
user_name: user.username, user_name: user.username,
password: encrypt(user.password), password: encrypt(user.password),
is_encrypt: 1, is_encrypt: 1,
...@@ -14,8 +14,38 @@ const accountLogin = user => dispatch => { ...@@ -14,8 +14,38 @@ const accountLogin = user => dispatch => {
}) })
} }
const studentLogin = params => dispatch => {
return http.post(`${API['passport-api']}/phone_reg`, {
challenge: params.validate,
phone: params.tel,
password: params.password,
code: params.code,
area_code: params.num,
school_name: params.school,
college_name: params.college,
student_id: params.uid,
student_name: params.name,
redirect: encodeURIComponent(params.redirect),
type: 1,
}).then(res => {
const { errno, data } = res.data;
let result = {};
if(errno === 0) {
result = {
data: {
errno: 200,
data,
}
};
}else {
result = res;
}
return storeUser(result, dispatch);
});
}
const quickLogin = user => dispatch => { const quickLogin = user => dispatch => {
return http.post(`${API['passport-api']}/quick_login`, { return http.post(`${API['passport-api']}/m/login/quickLogin`, {
...user, ...user,
plat: 5 plat: 5
}).then(res => { }).then(res => {
...@@ -26,7 +56,7 @@ const quickLogin = user => dispatch => { ...@@ -26,7 +56,7 @@ const quickLogin = user => dispatch => {
const storeUser = (res, dispatch) => { const storeUser = (res, dispatch) => {
const data = res.data const data = res.data
let payload let payload
if (data.errno === 0) { if (data.errno === 200) {
const {user_name: username, avatar_file: avatar,is_vip: isVIP, ...rest} = data.data.user_info const {user_name: username, avatar_file: avatar,is_vip: isVIP, ...rest} = data.data.user_info
payload = { payload = {
hasError: false, hasError: false,
...@@ -75,6 +105,7 @@ const startFetchUser = () => ({ ...@@ -75,6 +105,7 @@ const startFetchUser = () => ({
export { export {
accountLogin, accountLogin,
studentLogin,
SET_CURRENT_USER, SET_CURRENT_USER,
setCurrentUser, setCurrentUser,
quickLogin, quickLogin,
......
import { http, browser } from "@/utils" import { http, browser } from "@/utils"
const url = `https://res.wx.qq.com/open/js/jweixin-1.4.0.js` // const url = `https://res.wx.qq.com/open/js/jweixin-1.4.0.js`
const url = `https://res.wx.qq.com/open/js/jweixin-1.6.0.js`
const appId = 'wx23dac6775ac82877' const appId = 'wx23dac6775ac82877'
const jsApiList = ['updateAppMessageShareData','updateTimelineShareData','onMenuShareAppMessage', 'onMenuShareTimeline'] const jsApiList = ['updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareAppMessage', 'onMenuShareTimeline']
export const getSignature = async (config = {}) => { export const getSignature = async (config = {}) => {
let res = await http.post(`${API['base-api']}/m/sale/signature`, { let res = await http.post(`${API['base-api']}/m/sale/signature`, {
url: browser.isWeixin && browser.isIOS ? sessionStorage.getItem('enter_url') : window.location.href.split('#')[0], url: browser.isWeixin && browser.isIOS ? sessionStorage.getItem('enter_url') : window.location.href.split('#')[0],
}) })
return wx.config({ return wx.config({
debug: false, // 开启调试模式, debug: false, // 开启调试模式,
appId, // 必填,公众号的唯一标识 appId, // 必填,公众号的唯一标识
timestamp: res.data.timestamp, // 必填,生成签名的时间戳 timestamp: res.data.timestamp, // 必填,生成签名的时间戳
nonceStr: res.data.nonce_str, // 必填,生成签名的随机串 nonceStr: res.data.nonce_str, // 必填,生成签名的随机串
signature: res.data.signature,// 必填,签名,见附录1 signature: res.data.signature,// 必填,签名,见附录1
jsApiList, jsApiList,
...config ...config
}) })
} }
export const getWXObject = () => { export const getWXObject = () => {
return new Promise(resolve => { return new Promise(resolve => {
if (!window.wx) { if (!window.wx) {
return loadScript(url).then(() => resolve()) return loadScript(url).then(() => resolve())
} }
resolve() resolve()
}) })
} }
function loadScript(url) { function loadScript(url) {
return new Promise(resolve => { return new Promise(resolve => {
var head = document.head || document.getElementsByTagName('head')[0] var head = document.head || document.getElementsByTagName('head')[0]
var script = document.createElement('script') var script = document.createElement('script')
script.type = 'text/javascript' script.type = 'text/javascript'
script.src = url script.src = url
if (!('onload' in script)) { if (!('onload' in script)) {
script.onreadystatechange = function () { script.onreadystatechange = function () {
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
this.onreadystatechange = null this.onreadystatechange = null
resolve() resolve()
} }
} }
script.onload = function () { script.onload = function () {
this.onload = null this.onload = null
resolve() resolve()
} }
head.appendChild(script) head.appendChild(script)
}) })
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment