Commit 5c5de6e3 by zhanghaozhe

Merge branch 'limit-free' into dev

parents 3acad2bd 51265987
...@@ -269,10 +269,12 @@ function CourseList({modules, toDetail}) { ...@@ -269,10 +269,12 @@ function CourseList({modules, toDetail}) {
{item.is_buy {item.is_buy
? <a className="isbuy">已购买</a> ? <a className="isbuy">已购买</a>
: item.is_limit_free : item.is_limit_free
? <p className={'course-price'}> ? <Link to={`/detail?id=${item.course_id}`}>
<span className={'free'}>免费领取</span> <p className={'course-price'}>
<span className={'old'}>¥{item.price}</span> <span className={'free'}>免费领取</span>
</p> <span className={'old'}>¥{item.price}</span>
</p>
</Link>
: <p className="course-price"> : <p className="course-price">
<span className="new">¥{item.discounts_price}</span> <span className="new">¥{item.discounts_price}</span>
<span className="old">¥{item.price}</span> <span className="old">¥{item.price}</span>
......
...@@ -525,14 +525,20 @@ class BtnStatus extends Component { ...@@ -525,14 +525,20 @@ class BtnStatus extends Component {
} }
{ {
//todo 联调
info.is_limit_free && info.limit_free_status == 0 && <div className='btns-box'> info.is_limit_free && info.limit_free_status == 0 && <div className='btns-box'>
<a className='consult consult-m' onClick={()=>this.qimoChatClick()}> <a className='consult consult-m' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji'></i> <i className='iconfont iconerji'></i>
<span>课程咨询</span> <span>课程咨询</span>
</a> </a>
<button className={'get-course btn'} onClick={() => {this.props.getCourse(info.course_id)}}>立即领取</button> <button className={'get-course btn'} onClick={() => {
const {history, user, getCourse} = this.props
if(user.hasError){
history.push('/passport')
}else {
getCourse(info.course_id)
}
}}>立即领取</button>
</div> </div>
} }
......
...@@ -523,6 +523,7 @@ class Detail extends Component { ...@@ -523,6 +523,7 @@ class Detail extends Component {
</button> </button>
<button onClick={() => { <button onClick={() => {
history.push(`/play/video?id=${id}`) history.push(`/play/video?id=${id}`)
instance.close()
}}>立即学习 }}>立即学习
</button> </button>
</div> </div>
...@@ -539,6 +540,8 @@ class Detail extends Component { ...@@ -539,6 +540,8 @@ class Detail extends Component {
render() { render() {
const {course: {course_info = {}}, barInfo, singleBox, singleType, isRedPacket, countDownTime} = this.state; const {course: {course_info = {}}, barInfo, singleBox, singleType, isRedPacket, countDownTime} = this.state;
const {d, h, m} = this.formatTime(course_info.limit_free_time)
let courseInfo = '', let courseInfo = '',
service = '', service = '',
number = 0, number = 0,
...@@ -616,7 +619,6 @@ class Detail extends Component { ...@@ -616,7 +619,6 @@ class Detail extends Component {
</div> </div>
} }
{ {
//todo 联调
course_info.is_limit_free course_info.is_limit_free
? ?
course_info.limit_free_status == 0 course_info.limit_free_status == 0
...@@ -627,7 +629,7 @@ class Detail extends Component { ...@@ -627,7 +629,7 @@ class Detail extends Component {
: :
course_info.limit_free_status == 1 course_info.limit_free_status == 1
? <div className={'time-limit'}> ? <div className={'time-limit'}>
<span>有效期7天,051423分后过期</span> <span>有效期7天,{d}{h}{m}分后过期</span>
</div> </div>
: null : null
: null : null
...@@ -649,15 +651,15 @@ class Detail extends Component { ...@@ -649,15 +651,15 @@ class Detail extends Component {
is_vip 1是属于vip赠的 0是不在vip范围内的 is_vip 1是属于vip赠的 0是不在vip范围内的
*/} */}
{ {
course_info.is_baoming === 1 && course_info.is_pay == 1 && course_info.contact_type == 1 && course_info.course_qq && !(course_info.is_limit_free && course_info.limit_free_status == 1) && course_info.is_baoming === 1 && course_info.is_pay == 1 && course_info.contact_type == 1 && course_info.course_qq &&
<div className='group'> <div className='group'>
上课QQ群:{course_info.course_qq},加群请备注您的学号:{course_info.uid} 上课QQ群:{course_info.course_qq},加群请备注您的学号:{course_info.uid}
</div> </div>
} }
{ {
course_info.is_baoming === 1 && course_info.is_pay == 1 && course_info.contact_type == 2 && course_info.course_qq && !(course_info.is_limit_free && course_info.limit_free_status == 1) && course_info.is_baoming === 1 && course_info.is_pay == 1 && course_info.contact_type == 2 && course_info.course_qq &&
<div className='group'> <div className='group'>
请添加班主任微信:{course_info.course_qq},添加时备注学号:{course_info.uid} 请添加班主任微信:{course_info.course_qq},添加时备注学号:{course_info.uid}
</div> </div>
} }
......
...@@ -92,7 +92,11 @@ class LimitFree extends Component { ...@@ -92,7 +92,11 @@ class LimitFree extends Component {
this.getData() this.getData()
}}>知道了 }}>知道了
</button> </button>
<button onClick={this.toPlay.bind(this, id)}>立即学习</button> <button onClick={() => {
this.toPlay(id)
instance.close()
}}>立即学习
</button>
</div> </div>
}) })
...@@ -169,7 +173,11 @@ class LimitFree extends Component { ...@@ -169,7 +173,11 @@ class LimitFree extends Component {
bottom = <div className={'bottom'}> bottom = <div className={'bottom'}>
<span className={'red'}>限时免费</span> <span className={'red'}>限时免费</span>
<span className={'origin-price'}>¥{item.price0}</span> <span className={'origin-price'}>¥{item.price0}</span>
<button onClick={this.getCourse.bind(this, item.course_id)}>免费领取</button> <button onClick={e => {
e.stopPropagation()
this.getCourse(item.course_id)
}}>免费领取
</button>
</div> </div>
break break
case 1: case 1:
......
...@@ -18,7 +18,6 @@ class Purchased extends Component { ...@@ -18,7 +18,6 @@ class Purchased extends Component {
componentDidMount() { componentDidMount() {
this.getList() this.getList()
this.limitFreeCountDown()
} }
// 获取订单 // 获取订单
...@@ -41,14 +40,6 @@ class Purchased extends Component { ...@@ -41,14 +40,6 @@ class Purchased extends Component {
history.push(`/detail?id=${id}`) history.push(`/detail?id=${id}`)
// })); // }));
} }
limitFreeCountDown = timestamp => {
//todo 联调
const later = new Date(timestamp)
const earlier = Date.now()
return dateCountDown(later, earlier)
}
render() { render() {
const {user} = this.props const {user} = this.props
const uid = user && user.data && user.data.uid const uid = user && user.data && user.data.uid
...@@ -84,8 +75,7 @@ class Purchased extends Component { ...@@ -84,8 +75,7 @@ class Purchased extends Component {
</div> </div>
) )
const status = ( const status = (
// item.is_aist && <span className='status'>返现</span> item.is_aist && <span className='status'>返现</span>
<span className='limit-free-status'>{'*'}{'*'}{'*'}分后过期</span>
) )
const courseExpire = ( const courseExpire = (
item.course_expire && item.course_expire != '' && item.course_expire && item.course_expire != '' &&
......
...@@ -112,20 +112,6 @@ html, body, #root { ...@@ -112,20 +112,6 @@ html, body, #root {
background: linear-gradient(to bottom, #FF4000, #FD7700); background: linear-gradient(to bottom, #FF4000, #FD7700);
} }
.limit-free-status {
position: absolute;
right: 0;
top: 8px;
width: 112px;
height: 20px;
background: #FF0000;
border-radius: 10px 0 0 10px;
line-height: 20px;
color: #fff;
text-align: center;
font-size: 11px;
}
.course-expire { .course-expire {
display: inline-block; display: inline-block;
text-align: center; text-align: center;
......
...@@ -11,200 +11,199 @@ import { Loading } from "@/common"; ...@@ -11,200 +11,199 @@ import { Loading } from "@/common";
function getStudyTime(seconds) { function getStudyTime(seconds) {
return { return {
hour: Math.floor(seconds / (60 * 60)), hour: Math.floor(seconds / (60 * 60)),
min: Math.floor(seconds / 60) % 60, min: Math.floor(seconds / 60) % 60,
sec: seconds % 60 sec: seconds % 60
} }
} }
const AddCourse = React.memo(({addCourseClick}) => ( const AddCourse = React.memo(({addCourseClick}) => (
<div className='add-course'> <div className='add-course'>
<button className='add' onClick={addCourseClick}>添加课程+</button> <button className='add' onClick={addCourseClick}>添加课程+</button>
</div> </div>
)) ))
function Record({record: {seconds, lesson_name}}) { function Record({record: {seconds, lesson_name}}) {
let re = /第[\s\S]+?课/, let re = /第[\s\S]+?课/,
result = '' result = ''
if (lesson_name) { if (lesson_name) {
let matchResult = re.exec(lesson_name) let matchResult = re.exec(lesson_name)
result += (matchResult && matchResult[0]) ? matchResult[0] : '' result += (matchResult && matchResult[0]) ? matchResult[0] : ''
} }
if (seconds) { if (seconds) {
let studyTime = getStudyTime(seconds) let studyTime = getStudyTime(seconds)
let hour = studyTime.hour ? String(studyTime.hour).padStart(2, '0') + ':' : '', let hour = studyTime.hour ? String(studyTime.hour).padStart(2, '0') + ':' : '',
min = studyTime.min ? String(studyTime.min).padStart(2, '0') + ':' : '', min = studyTime.min ? String(studyTime.min).padStart(2, '0') + ':' : '',
sec = studyTime.sec ? String(studyTime.sec).padStart(2, '0') : '' sec = studyTime.sec ? String(studyTime.sec).padStart(2, '0') : ''
result += hour + min + sec result += hour + min + sec
} }
return ( return (
<span className={'record'}> <span className={'record'}>
{ {
result.length ? `学习到${result}` : null result.length ? `学习到${result}` : null
} }
</span> </span>
) )
} }
const Bottom = React.memo(({item}) => { const Bottom = React.memo(({item}) => {
if (item.ago || item.seconds) { if (item.ago || item.seconds) {
let date = new Date(item.ago * 1000) let date = new Date(item.ago * 1000)
let time = isToday(date) ? format(date, 'HH时mm分') : format(date, 'MM月DD日') let time = isToday(date) ? format(date, 'HH时mm分') : format(date, 'MM月DD日')
return (
<div className="des">
<span className='time'>{time}</span>
<Record record={item}/>
</div>
)
}
return ( return (
<button className='start-learn'>开始学习</button> <div className="des">
<span className='time'>{time}</span>
<Record record={item}/>
</div>
) )
}
return (
<button className='start-learn'>开始学习</button>
)
}) })
class MyCourses extends Component { class MyCourses extends Component {
list list
state = { state = {
isLoading: true isLoading: true
} }
handleClick = (id, item) => {
const {history} = this.props
const {mode, course_id} = item
if(mode && mode == 6){
history.push(`/python?id=${course_id}`)
return
}
history.push(`/play/video?id=${id}`)
}
addCourseClick = () => {
this.props.history.push('/classify')
}
componentDidMount() { handleClick = (id, item) => {
this.props.switchTab(false) const {history} = this.props
this.props.fetchCoursesListIfNeeded() const {mode, course_id} = item
if (mode && mode == 6) {
history.push(`/python?id=${course_id}`)
return
} }
history.push(`/play/video?id=${id}`)
componentWillUnmount() { }
this.props.switchTab(true); addCourseClick = () => {
this.props.history.push('/classify')
}
componentDidMount() {
this.props.switchTab(false)
this.props.fetchCoursesListIfNeeded()
}
componentWillUnmount() {
this.props.switchTab(true);
}
loadFunc = debounce(() => {
if (this.props.courseList.length % 10 === 0) {
this.props.fetchCoursesListIfNeeded()
} }
}, 200)
render() {
let {courseList, user} = this.props
return <Loading isLoading={this.props.isLoading}>
{
courseList && courseList.length !== 0
?
<>
<div className="my-course-uid">
{`加群请备注您的学号:${!user.hasError && this.props.user.data.uid}`}
</div>
<InfiniteScroll
pageStart={0}
hasMore={true}
loadMore={this.loadFunc}
useWindow={false}
>
<ul ref={el => this.list = el}>
{
courseList.map((item, index) => {
const Info = (
<div className="info">
<div className='title'>{item.course_title}</div>
{
item.is_aist &&
<div className='contact'>助教微信:{item.assist_weixin}</div>
}
{
!item.is_aist && item.contact_type == 1 && item.course_qq &&
<div className='contact'>QQ群:{item.course_qq}</div>
}
{
!item.is_aist && item.contact_type == 2 && item.course_qq &&
<div className='contact'>班主任微信:{item.course_qq}</div>
}
loadFunc = debounce(() => {
if (this.props.courseList.length % 10 === 0) {
this.props.fetchCoursesListIfNeeded()
}
}, 200)
render() {
let {courseList, user} = this.props
return <Loading isLoading={this.props.isLoading}>
{
courseList && courseList.length !== 0
?
<>
<div className="my-course-uid">
{`加群请备注您的学号:${!user.hasError && this.props.user.data.uid}`}
</div>
<InfiniteScroll
pageStart={0}
hasMore={true}
loadMore={this.loadFunc}
useWindow={false}
>
<ul ref={el => this.list = el}>
{
courseList.map((item, index) => {
const Info = (
<div className="info">
<div className='title'>{item.course_title}</div>
{
item.is_aist &&
<div className='contact'>助教微信:{item.assist_weixin}</div>
}
{
!item.is_aist && item.contact_type == 1 && item.course_qq &&
<div className='contact'>QQ群:{item.course_qq}</div>
}
{
!item.is_aist && item.contact_type == 2 && item.course_qq &&
<div className='contact'>班主任微信:{item.course_qq}</div>
}
{
item.is_aist && item.aist_schedule &&
<div className="process-status">
<div className="process-wrapper">
<div className="process-bar"
style={{width: `${parseFloat(item.aist_schedule)}%`}}/>
</div>
<div className="process-text">{item.aist_schedule}</div>
</div>
}
<Bottom item={item}/>
</div>
)
const status = (
item.is_aist && <span className='status'>返现</span>
)
const courseExpire = (
item.course_expire && item.course_expire!='' &&
<span className='course-expire'>{item.course_expire}</span>
)
return (
<VList img={item.image_name}
handleClick={this.handleClick}
{...item}
key={index}
info={Info}
status={status}
courseExpire={courseExpire}
item={item}
id={item['v_course_id']}
/>
)
})
}
</ul>
</InfiniteScroll>
{ {
courseList.length % 10 !== 0 ? item.is_aist && item.aist_schedule &&
<AddCourse addCourseClick={this.addCourseClick}/> <div className="process-status">
: null <div className="process-wrapper">
<div className="process-bar"
style={{width: `${parseFloat(item.aist_schedule)}%`}}/>
</div>
<div className="process-text">{item.aist_schedule}</div>
</div>
} }
</> <Bottom item={item}/>
: </div>
<div className="empty"> )
<p><i className='iconfont iconfish'/></p>
<p className='empty-prompt'>您还没有课程哦,赶快去选课吧~</p> const status = (
<p> item.is_aist
<Link className='select-course' to='/classify'>去选课</Link> ? <span className='status'>返现</span>
</p> : item.course_expire
</div> ? <span className='course-expire'>{item.course_expire}</span>
: null
)
return (
<VList img={item.image_name}
handleClick={this.handleClick}
{...item}
key={index}
info={Info}
status={status}
item={item}
id={item['v_course_id']}
/>
)
})
}
</ul>
</InfiniteScroll>
{
courseList.length % 10 !== 0 ?
<AddCourse addCourseClick={this.addCourseClick}/>
: null
} }
</Loading> </>
:
} <div className="empty">
<p><i className='iconfont iconfish'/></p>
<p className='empty-prompt'>您还没有课程哦,赶快去选课吧~</p>
<p>
<Link className='select-course' to='/classify'>去选课</Link>
</p>
</div>
}
</Loading>
}
} }
export default connect( export default connect(
state => ({ state => ({
courseList: state.myCourses.courseList, courseList: state.myCourses.courseList,
user: state.user, user: state.user,
isLoading: state.myCourses.isLoading isLoading: state.myCourses.isLoading
}), }),
{ {
fetchCoursesListIfNeeded, fetchCoursesListIfNeeded,
switchTab switchTab
})(MyCourses) })(MyCourses)
import React, { Component } from 'react' import React, { Component } from 'react'
import HeaderBar from '@/common/HeaderBar' import HeaderBar from '@/common/HeaderBar'
import './video.scss' import './video.scss'
import { NavLink, Route, Redirect, Switch} from 'react-router-dom' import { NavLink, Route, Redirect, Switch } from 'react-router-dom'
import { http, getParam, browser } from '@/utils' import { http, getParam, browser } from '@/utils'
import Recommendation from './recommendation' import Recommendation from './recommendation'
import VideoCatalog from './video-catalog' import VideoCatalog from './video-catalog'
...@@ -9,8 +9,8 @@ import DatumCatalog from './datum-catalog' ...@@ -9,8 +9,8 @@ import DatumCatalog from './datum-catalog'
import { Toast } from 'antd-mobile' import { Toast } from 'antd-mobile'
import videojs from 'video.js' import videojs from 'video.js'
import 'video.js/dist/video-js.min.css' import 'video.js/dist/video-js.min.css'
import { Modal} from "antd-mobile" 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 Single from "@/components/detail/single"; import Single from "@/components/detail/single";
...@@ -104,12 +104,12 @@ class Video extends Component { ...@@ -104,12 +104,12 @@ class Video extends Component {
nowPrice: 0,// 单集购买需要 nowPrice: 0,// 单集购买需要
laterPrice: 0,// 单集购买需要 laterPrice: 0,// 单集购买需要
limitFreeNoPromptChecked: false, limitFreeNoPromptChecked: false,
showLimitFreePopup: true //todo 联调 showLimitFreePopup: false,
limitFreePopup: {}
} }
componentDidMount() { componentDidMount() {
console.log(this.props.location.hash)
if (window.location.protocol === 'https:') { if (window.location.protocol === 'https:') {
window.location.replace('http' + window.location.href.slice(5)) window.location.replace('http' + window.location.href.slice(5))
return return
...@@ -527,6 +527,11 @@ class Video extends Component { ...@@ -527,6 +527,11 @@ class Video extends Component {
} }
clearInterval(this.timer); clearInterval(this.timer);
this.timer = null; this.timer = null;
if (this.state.limitFreePopup.is_free) {
this.setState({
showLimitFreePopup: true
})
}
}) })
} }
...@@ -607,6 +612,7 @@ class Video extends Component { ...@@ -607,6 +612,7 @@ class Video extends Component {
}), }),
this.playSetup this.playSetup
) )
this.getLimitFreePopup(data.course.course_id)
} else { } else {
Toast.info(data.msg) Toast.info(data.msg)
} }
...@@ -736,9 +742,54 @@ class Video extends Component { ...@@ -736,9 +742,54 @@ class Video extends Component {
} }
} }
getLimitFreePopup = id => {
http.post(`${API.home}/sys/popup`, {
course_id: id
})
.then(res => {
const {code, msg, data} = res.data
if (code === 200) {
this.setState({
limitFreePopup: data
})
} else {
Toast.info(msg, 2, null, false)
}
})
}
checkNeverShowLimitFreePopup = () => {
http.post(`${API.home}/sys/checklist`, {
course_id: this.state.course.course_id
})
.then(res => {
const {code, msg} = res.data
if (code === 200) {
this.setState({
limitFreePopup: {...this.state.limitFreePopup, is_free: 0}
})
}else {
Toast.info(msg, 2, null, false)
}
})
}
render() { render() {
let {match, location, history} = this.props let {match, location, history} = this.props
const {videoList, activeIndex, isAuth, salePrice, course, singleBox, singleType, showLimitFreePopup} = this.state; const {
videoList,
activeIndex,
isAuth,
salePrice,
course,
singleBox,
singleType,
showLimitFreePopup,
limitFreePopup
} = this.state;
let toHref = ''; let toHref = '';
if (location.state && location.state.to && location.state.to === 'detail') { if (location.state && location.state.to && location.state.to === 'detail') {
toHref = `/detail?id=${course.course_id}` toHref = `/detail?id=${course.course_id}`
...@@ -875,13 +926,13 @@ class Video extends Component { ...@@ -875,13 +926,13 @@ class Video extends Component {
<div className={'limit-free-cover'}> <div className={'limit-free-cover'}>
<div className="free-popup"> <div className="free-popup">
<div className="title"> <div className="title">
<span>想领取【AI工程师必备干货礼包】? 想深入了解进阶课程? 职业前景不明朗? 资深规划师免费为你服务!</span> <span>{limitFreePopup.pop_descbition}</span>
</div> </div>
<div className={'des'}> <div className={'des'}>
<img className="qrcode" <img className="qrcode"
src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/tinypng-common/right_weixin.png" alt=''/> src={limitFreePopup.wechat_img} alt=''/>
<span>长按/扫码识别</span> <span>长按/扫码识别</span>
<span>添加时请备注<span>142</span>哦</span> <span>添加时请备注<span>{course.course_id}</span>哦</span>
<div className="no-prompt"> <div className="no-prompt">
<label htmlFor="no-prompt"> <label htmlFor="no-prompt">
<span className={`checkbox-label ${this.state.limitFreeNoPromptChecked ? 'checked' : 'unchecked'}`}> <span className={`checkbox-label ${this.state.limitFreeNoPromptChecked ? 'checked' : 'unchecked'}`}>
...@@ -900,7 +951,7 @@ class Video extends Component { ...@@ -900,7 +951,7 @@ class Video extends Component {
this.setState({ this.setState({
showLimitFreePopup: false showLimitFreePopup: false
}) })
localStorage.setItem('neverShowLimitFreePopup', '1') this.checkNeverShowLimitFreePopup()
}}/> }}/>
</div> </div>
</div> </div>
......
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