Commit d3a588c3 by zhanghaozhe

Merge branch 'limit-free'

# Conflicts:
#	src/components/video/index.js
parents 9462f7d6 16faa68d
@font-face {font-family: "iconfont"; @font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1568272104473'); /* IE9 */ src: url('iconfont.eot?t=1583394769931'); /* IE9 */
src: url('iconfont.eot?t=1568272104473#iefix') format('embedded-opentype'), /* IE6-IE8 */ src: url('iconfont.eot?t=1583394769931#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('iconfont.woff?t=1568272104473') format('woff'), url('iconfont.woff?t=1583394769931') format('woff'),
url('iconfont.ttf?t=1568272104473') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('iconfont.ttf?t=1583394769931') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1568272104473#iconfont') format('svg'); /* iOS 4.1- */ url('iconfont.svg?t=1583394769931#iconfont') format('svg'); /* iOS 4.1- */
} }
.iconfont { .iconfont {
...@@ -15,64 +15,136 @@ ...@@ -15,64 +15,136 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.iconyanjing:before { .iconRectangleCopy4:before {
content: "\e667"; content: "\e6a5";
} }
.iconremen:before { .icontijikongjian:before {
content: "\e642"; content: "\e89f";
} }
.iconzhaopin:before { .iconshouye:before {
content: "\e67e"; content: "\e8b9";
} }
.iconshouji:before { .iconyonghu:before {
content: "\e66d"; content: "\e8c8";
} }
.iconqiye1:before { .iconall:before {
content: "\e669"; content: "\e6ef";
} }
.icon-jingsai:before { .iconbofangyedianzan:before {
content: "\e67f"; content: "\e687";
} }
.iconerji:before { .iconbofang:before {
content: "\e65f"; content: "\e686";
}
.icon04:before {
content: "\e685";
}
.icongengduo:before {
content: "\e650";
}
.iconalipay:before {
content: "\e684";
}
.iconplay_hovericon:before {
content: "\e683";
}
.iconpengyouquaniconx:before {
content: "\e604";
}
.iconyindao:before {
content: "\e72e";
} }
.iconss_empty:before { .iconss_empty:before {
content: "\e682"; content: "\e682";
} }
.iconcelluar:before {
content: "\e680";
}
.iconzhanghu_jiangjin:before { .iconzhanghu_jiangjin:before {
content: "\e681"; content: "\e681";
} }
.iconhuabei:before { .iconzhaopin:before {
content: "\e78c"; content: "\e67e";
} }
.iconyindao:before { .iconqiye1:before {
content: "\e72e"; content: "\e669";
} }
.iconpwd-hidden:before { .icon-jingsai:before {
content: "\e668"; content: "\e67f";
} }
.iconweixinzhifu:before { .icongouwuche-xianxing:before {
content: "\e662"; content: "\e67b";
}
.iconwode-chunse:before {
content: "\e643";
}
.iconwode-xianxing:before {
content: "\e666";
}
.iconxuexi-xianxing:before {
content: "\e665";
}
.iconxuexi-chunse:before {
content: "\e679";
}
.iconfenlei-chunse:before {
content: "\e678";
}
.iconfenlei-xianxing:before {
content: "\e677";
}
.iconshouye-xianxing:before {
content: "\e672";
}
.iconshouye1:before {
content: "\e66f";
} }
.iconmima:before { .iconmima:before {
content: "\e6cd"; content: "\e6cd";
} }
.iconyouhuiquan:before { .iconshouji:before {
content: "\e63c"; content: "\e66d";
}
.iconduanxin:before {
content: "\e66e";
}
.iconyanjing:before {
content: "\e667";
}
.iconpwd-hidden:before {
content: "\e668";
} }
.icondianzan:before { .icondianzan:before {
...@@ -83,8 +155,44 @@ ...@@ -83,8 +155,44 @@
content: "\ec8c"; content: "\ec8c";
} }
.iconduanxin:before { .iconhuabei:before {
content: "\e66e"; content: "\e78c";
}
.iconweixinzhifu:before {
content: "\e662";
}
.iconfrench_fries:before {
content: "\e675";
}
.iconfridge:before {
content: "\e674";
}
.iconerji:before {
content: "\e65f";
}
.iconremen:before {
content: "\e642";
}
.iconyouhuiquan:before {
content: "\e63c";
}
.icontea:before {
content: "\e67a";
}
.iconramen:before {
content: "\e67c";
}
.iconhoney:before {
content: "\e67d";
} }
.iconzhong:before { .iconzhong:before {
...@@ -479,79 +587,3 @@ ...@@ -479,79 +587,3 @@
content: "\e676"; content: "\e676";
} }
.iconfridge:before {
content: "\e674";
}
.icontea:before {
content: "\e67a";
}
.iconfrench_fries:before {
content: "\e675";
}
.iconramen:before {
content: "\e67c";
}
.iconhoney:before {
content: "\e67d";
}
.iconcelluar:before {
content: "\e680";
}
.iconshouye1:before {
content: "\e66f";
}
.iconshouye-xianxing:before {
content: "\e672";
}
.iconfenlei-xianxing:before {
content: "\e677";
}
.iconfenlei-chunse:before {
content: "\e678";
}
.iconxuexi-xianxing:before {
content: "\e665";
}
.iconxuexi-chunse:before {
content: "\e679";
}
.iconwode-chunse:before {
content: "\e643";
}
.iconwode-xianxing:before {
content: "\e666";
}
.icongouwuche-xianxing:before {
content: "\e67b";
}
.iconalipay:before {
content: "\e684";
}
.iconpengyouquaniconx:before {
content: "\e604";
}
.iconplay_hovericon:before {
content: "\e683";
}
.icongengduo:before {
content: "\e650";
}
No preview for this file type
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
No preview for this file type
No preview for this file type
No preview for this file type
.v-list-base-item { .v-list-base-item {
height: 130px; //height: 130px;
padding: 10px 10px 0; padding: 10px 10px 0;
position: relative; position: relative;
......
...@@ -12,386 +12,393 @@ import { Toast } from 'antd-mobile' ...@@ -12,386 +12,393 @@ import { Toast } from 'antd-mobile'
import { connect } from "react-redux"; import { connect } from "react-redux";
import TopSwiper from './TopSwiper' import TopSwiper from './TopSwiper'
import ExpandActiveToast from './expandActiveToast' import ExpandActiveToast from './expandActiveToast'
import CourseBase from '@/common/course-base'
import { switchTab } from "@components/study/myCourses/actions"
// const animateTypes = Swiper.animateTypes // const animateTypes = Swiper.animateTypes
@connect(state => ({ @connect(state => ({
user: state.user user: state.user
})) }))
class Index extends Component { class Index extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
banner: [], // 首页banner banner: [], // 首页banner
lives: [], //近期直播 lives: [], //近期直播
modules: [], //首页课程模块儿 modules: [], //首页课程模块儿
isShow: false, isShow: false,
islive: false, islive: false,
roomMess: '', roomMess: '',
tabdata: [ tabdata: [
{ {
'src': require('./image/freeclass_icon.png'), 'src': require('./image/freeclass_icon.png'),
'name': '公开课', 'name': '公开课',
'href': '/study/free-course' 'href': '/study/free-course'
}, },
{ {
'src': require('./image/jingpin_icon.png'), 'src': require('./image/jingpin_icon.png'),
'name': '精品特惠', 'name': '精品特惠',
'href': '/preferential' 'href': '/preferential'
}, },
{ {
'src': require('./image/zjxj_icon.png'), 'src': require('./image/zjxj_icon.png'),
'name': '赚奖学金', 'name': '赚奖学金',
'href': '/scholarship' 'href': '/scholarship'
}, },
{ {
'src': require('./image/mryt_icon.png'), 'src': require('./image/mryt_icon.png'),
'name': '每日一题', 'name': '每日一题',
'href': '/examination' 'href': '/examination'
}, },
{ {
'src': require('./image/shequ_icon.png'), 'src': require('./image/shequ_icon.png'),
'name': '社区', 'name': '社区',
'href': 'https://ask.julyedu.com' 'href': 'https://ask.julyedu.com'
}
]
} }
],
} }
}
componentDidMount() {
this.getIndexData()
}
// 首页课程
getIndexData = () => {
http.get(`${API.home}/m/home`).then((res) => {
if (res.data.code === 200) {
const {data} = res.data || {}
const modules = Array.isArray(data.modules) ? data.modules : []
this.setState({
banner: data.banner,
lives: data.lives,
modules
})
} else {
Toast.info(res.data.msg, 2)
}
componentDidMount() { })
this.getIndexData() }
}
// 首页课程
getIndexData = () => {
http.get(`${API.home}/m/home`).then((res) => {
if (res.data.code === 200) {
const {data} = res.data || {}
this.setState({
banner: data.banner,
lives: data.lives,
modules: typeof data.modules === 'object' && data.modules.length > 0 ? data.modules : []
})
} else {
Toast.info(res.data.msg, 2)
}
// 点击近期直播课程弹出预约提示框
liveCourse = (item) => {
const {user} = this.props
const uid = user && user.data && user.data.uid
if (!uid) {
this.props.history.push('/passport/login')
} else {
if (item.live_status === 0) {
this.setState({
isShow: true,
islive: true,
roomMess: item
}) })
} else {
window.location.href = `${window.location.href.includes('pre') ? 'http://www-pre.julyedu.com' : 'http://www.julyedu.com'}/live/m_room/${item.room_id}`
}
} }
}
// 自组件传给父组件的isshow
colseBox = (val) => {
this.setState({isShow: val})
}
// 点击头部搜索跳转到搜索页面
toSearch() {
this.props.history.push('/search')
}
toCourseDetail = (id) => {
const {history} = this.props;
history.push(`/detail?id=${id}`);
return false;
}
render() {
return (
<div className='index-box'>
<div className='header'>
<img
className="logo"
src="http://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/img/index/logo.png"
alt=""
/>
<CallApp
className='to-app'
text='在APP打开'
/>
<i
className='iconfont iconiconfront- search'
onClick={this.toSearch.bind(this)}
/>
</div>
<div className='zw_height'></div>
// 点击近期直播课程弹出预约提示框 <ExpandActiveToast/>
liveCourse = (item) => {
const {user} = this.props
const uid = user && user.data && user.data.uid
if (!uid) {
this.props.history.push('/passport/login')
} else {
if (item.live_status === 0) {
this.setState({
isShow: true,
islive: true,
roomMess: item
})
} else {
window.location.href = `${window.location.href.includes('pre') ? 'http://www-pre.julyedu.com' : 'http://www.julyedu.com'}/live/m_room/${item.room_id}`
}
}
}
// 自组件传给父组件的isshow
colseBox = (val) => {
this.setState({isShow: val})
}
// 点击头部搜索跳转到搜索页面 <div className='index-swiper'>
toSearch() { {
this.props.history.push('/search') this.state.banner && this.state.banner.length > 0 &&
} <TopSwiper bannerList={this.state.banner}/>
}
</div>
toCourseDetail = (id) => { <div className="tabbox">
const {dispatch, history} = this.props; <ul>
// dispatch(getCourses(id, () => { {
history.push(`/detail?id=${id}`); this.state.tabdata.map((item, index) => {
return false; return (
// })); <li key={index}>
} <a href={item.href}>
<img src={item.src} alt=""/>
<span>{item.name}</span>
</a>
</li>
)
})
}
</ul>
</div>
render() { <p className="borderTop"/>
return (
<div className='index-box'>
<div className='header'>
<img
className="logo"
src="http://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/img/index/logo.png"
alt=""
/>
<CallApp
className='to-app'
text='在APP打开'
/>
<i
className='iconfont iconiconfront- search'
onClick={this.toSearch.bind(this)}
/>
</div>
<div className='zw_height'></div> {
<ExpandActiveToast/> (this.state.lives && this.state.lives.length > 0) ?
<div className='lives'>
<h2 className="title">近期直播</h2>
<ScrollBox
livesList={this.state.lives}
liveCourse={this.liveCourse}
/>
</div> : null
}
<div className='index-swiper'> {
{ (this.state.modules && this.state.modules.length > 0) ? this.state.modules.map((item, index) => {
this.state.banner && this.state.banner.length > 0 && return (
<TopSwiper bannerList={this.state.banner}/> <div key={index}>
} <CourseList
</div> modules={item}
toDetail={this.toCourseDetail}
/>
<p className="borderTop"/>
</div>
)
}) : null
}
<div className="tabbox"> <div className="category all-course">
<ul> <Link to='/classify'>
{ <p>查看全部课程</p>
this.state.tabdata.map((item, index) => { <span>数学基础、数学结构、大数据实战、Python...</span>
return ( </Link>
<li key={index}> </div>
<a href={item.href}>
<img src={item.src} alt=""/>
<span>{item.name}</span>
</a>
</li>
)
})
}
</ul>
</div>
<p className="borderTop"/> {/* 直播间预约 */}
{
this.state.islive &&
<LiveRoom
isShow={this.state.isShow}
colseBox={this.colseBox}
roomMess={this.state.roomMess}
getIndexData={this.getIndexData}
/>
}
</div>
)
}
{ }
(this.state.lives && this.state.lives.length > 0) ? // 课程模块儿公共组件
<div className='lives'> // 课程数量是奇数第一个课程需要横着展示沾满一行,课程数量是偶数一行显示两个
<h2 className="title">近期直播</h2> function CourseList({modules, toDetail}) {
<ScrollBox
livesList={this.state.lives}
liveCourse={this.liveCourse}
/>
</div> : null
}
{ let filterList = []
(this.state.modules && this.state.modules.length > 0) ? this.state.modules.map((item, index) => { let isOdd = modules.list.length % 2 === 0
return (
<div key={index}>
<CourseList
modules={item}
toDetail={this.toCourseDetail}
/>
<p className="borderTop"/>
</div>
)
}) : null
}
<div className="category all-course"> if (modules.name === '限时免费') {
<Link to='/classify'> filterList = modules.list
<p>查看全部课程</p> } else {
<span>数学基础、数学结构、大数据实战、Python...</span> // 数量为奇数时,第一个课程显示大图(如后台未上传,前台显示小图),课程数量为偶数时,均显示小图
</Link>
</div>
{/* 直播间预约 */} if (isOdd) {
{ filterList = modules.list
this.state.islive && } else {
<LiveRoom filterList = modules.list[0].course_img === modules.list[0].course_img_small ? modules.list : modules.list.slice(1)
isShow={this.state.isShow}
colseBox={this.colseBox}
roomMess={this.state.roomMess}
getIndexData={this.getIndexData}
/>
}
</div>
)
} }
}
}
return (
<div className='category'>
<h2 className="title">
{modules.name}
{
modules.name === '限时免费' && <span className={'hot'}>hot</span>
}
</h2>
{
modules.show_more === 1 &&
<Link className="more" to='/classify'>更多 ></Link>
}
{
modules.show_more === 2 ?
modules.name === '限时免费'
? <Link className="more" to={'/free'}>更多 ></Link>
: <Link className="more" to={modules.more_page}>更多 ></Link>
: null
}
<LazyLoad offset={50}>
<ul className='index-course-detail'>
{
modules.name !== '限时免费' && !isOdd && modules.list[0].course_img !== modules.list[0].course_img_small &&
<div className="category-vip" onClick={() => toDetail(modules.list[0].course_id)}>
<img src={modules.list[0].course_img} alt=""/>
</div>
}
{
filterList.map((item, index) => {
const top = item.is_limit_free ? null : (
<div>
{item.is_audition === true &&
<span className='audition'><i className={'iconfont iconerji'}></i>试听</span>
}
{item.is_aist &&
<span className='return_bash'></span>
}
</div>
)
// function TopSwiper({bannerList}) { const bottom = <Bottom course={item}/>
// return (
// <Swiper
// type={animateTypes.CARD}
// loop={true}
// height={168}
// autoPlay={true}
// typePro
// createStyle={createStyle}
// >
// {bannerList && bannerList.length > 0 && bannerList.map((item, index) => {
// return (
// Number.isNaN(parseInt(item.jump_url)) ?
// <a href={item.jump_url} key={index}>
// {/* <Link to={item.jump_url} key={index}> */}
// <img className="item" src={item.name} alt="" />
// {/* </Link> */}
// </a> :
// <Link
// to={{
// pathname: '/detail',
// search: `?id=${item.jump_url}`
// }}
// key={index}
// >
// <img
// className="item"
// src={item.name}
// alt=""
// />
// </Link>
// )
// })
// }
// </Swiper>
// )
// }
// 课程模块儿公共组件 const status = item.is_limit_free ? null : <div>
// 课程数量是奇数第一个课程需要横着展示沾满一行,课程数量是偶数一行显示两个 {item.is_bargain &&
function CourseList({modules, toDetail}) { <p className='course-status'>砍价减{item.bargain_price}</p>
let isOdd = modules.list.length % 2 === 0 }
// 数量为奇数时,第一个课程显示大图(如后台未上传,前台显示小图),课程数量为偶数时,均显示小图 {item.is_groupon &&
let filterList = '' <p className='course-status'>拼团价{item.groupon_price}</p>
}
</div>
return (
<Course
key={index}
top={top}
data={item}
bottom={bottom}
status={status}
img={item.course_img_small}
title={item.course_title}
id={item.course_id}
toDetail={toDetail}
className='text-overflow-2'
/>
)
})
}
</ul>
</LazyLoad>
</div>
)
}
if (isOdd) { //限时免费
filterList = modules.list function LimitFree({course}) {
/*
*
* limit_free_status: 0-未领取 1-已领取 2-已过期
*
* */
switch (course.limit_free_status) {
case 0:
return <Link to={`/detail?id=${course.course_id}`}>
<p className={'course-price'}>
<span className={'free'}>免费领取</span>
<span className={'old'}>¥{course.price}</span>
</p>
</Link>
case 1:
return <div className={'isbuy'}>已领取</div>
default:
return <p className="course-price">
<span className="new">¥{course.discounts_price}</span>
<span className="old">¥{course.price}</span>
</p>
}
}
//课程底部
function Bottom({course}) {
if (course.is_buy) {
if (course.is_limit_free && course.limit_free_status === 1) {
return <div class={'isbuy'}>已领取</div>
} else { } else {
filterList = modules.list[0].course_img === modules.list[0].course_img_small ? modules.list : modules.list.slice(1) return <div className={'isbuy'}>已购买</div>
} }
return ( } else {
<div className='category'> return course.is_limit_free
<h2 className="title">{modules.name}</h2> ? <LimitFree course={course}/>
{ : <p className="course-price">
modules.show_more === 1 && <span className="new">¥{course.discounts_price}</span>
<Link className="more" to='/classify'>更多 ></Link> <span className="old">¥{course.price}</span>
} </p>
{ }
modules.show_more === 2 &&
<Link className="more" to={modules.more_page}>更多 ></Link>
}
<LazyLoad offset={50}>
<ul className='index-course-detail'>
{
!isOdd && modules.list[0].course_img !== modules.list[0].course_img_small &&
<div className="category-vip" onClick={() => toDetail(modules.list[0].course_id)}>
{/* <Link to={`/detail?id=${modules.list[0].course_id}`}> */}
<img src={modules.list[0].course_img} alt=""/>
{/* </Link> */}
</div>
}
{
filterList.map((item, index) => {
const top = (
<div>
{item.is_audition === true &&
<span className='audition'><i className={'iconfont iconerji'}></i>试听</span>
}
{item.is_aist &&
<span className='return_bash'></span>
}
</div>
);
const bottom = (
<div>
{!item.isbuy && <p className="course-price">
<span className="new">¥{item.discounts_price}</span>
<span className="old">¥{item.price}</span>
</p>
}
{item.isbuy &&
<a className="isbuy">已购买</a>
}
</div>
)
const status = (
<div>
{item.is_bargain &&
<p className='course-status'>砍价减{item.bargain_price}</p>
}
{item.is_groupon &&
<p className='course-status'>拼团价{item.groupon_price}</p>
}
</div>
)
return (
<Course
key={index}
top={top}
data={item}
bottom={bottom}
status={status}
img={item.course_img_small}
title={item.course_title}
id={item.course_id}
toDetail={toDetail}
className='text-overflow-2'
/>
)
})
}
</ul>
</LazyLoad>
</div>
)
} }
//近期直播 //近期直播
function ScrollBox(props) { function ScrollBox(props) {
return ( return (
<div className='scroll-box'> <div className='scroll-box'>
<ul className='scroll-list'> <ul className='scroll-list'>
{ {
props.livesList && props.livesList.length > 0 && props.livesList.map((item, index) => { props.livesList && props.livesList.length > 0 && props.livesList.map((item, index) => {
return ( return (
<li key={index} className='scroll-item' <li key={index} className='scroll-item'
onClick={e => props.liveCourse(item)}> onClick={e => props.liveCourse(item)}>
<div className='item-box'> <div className='item-box'>
{ {
item.live_status === 0 && item.live_status === 0 &&
<span className='no-start'>即将开始</span> <span className='no-start'>即将开始</span>
} }
{ {
(item.live_status === 1 || item.live_status === 10) && (item.live_status === 1 || item.live_status === 10) &&
<span className='start'>正在直播</span> <span className='start'>正在直播</span>
} }
<img className="item-img" src={item.live_img} alt=""/> <img className="item-img" src={item.live_img} alt=""/>
<div className="item-content"> <div className="item-content">
<h2 className="item-title">{item.live_title}</h2> <h2 className="item-title">{item.live_title}</h2>
<p className="item-teacher">讲师:{item.live_teacher_name}</p> <p className="item-teacher">讲师:{item.live_teacher_name}</p>
{/*公开课需预约、付费课不需要预约*/} {/*公开课需预约、付费课不需要预约*/}
{ {
(item.is_prepare || item.is_free === 0) && item.live_status === 0 && (item.is_prepare || item.is_free === 0) && item.live_status === 0 &&
<p className="item-time">时间:{item.live_start_time}</p> <p className="item-time">时间:{item.live_start_time}</p>
} }
{ {
!item.is_prepare && item.live_status === 0 && item.is_free === 1 && !item.is_prepare && item.live_status === 0 && item.is_free === 1 &&
<button className='item-btn'>预约</button> <button className='item-btn'>预约</button>
} }
{ {
(item.live_status === 1 || item.live_status === 10) && (item.live_status === 1 || item.live_status === 10) &&
<button className='item-btn'>正在直播</button> <button className='item-btn'>正在直播</button>
} }
</div> </div>
</div> </div>
</li> </li>
) )
}) })
} }
</ul> </ul>
</div> </div>
) )
} }
export default WithTab(Index); export default WithTab(Index);
#chatBtn { #chatBtn {
bottom: 60px!important; bottom: 60px !important;
} }
.index-box { .index-box {
overflow: hidden; overflow: hidden;
background-color: $bg_fff; background-color: $bg_fff;
...@@ -283,6 +284,20 @@ ...@@ -283,6 +284,20 @@
font-size: 16px; font-size: 16px;
color: $color_333; color: $color_333;
display: inline-block; display: inline-block;
.hot {
display: inline-block;
width: 25px;
height: 14px;
margin-left: 5px;
transform: translateY(-5px);
background: rgba(255, 64, 0, 1);
border-radius: 7px 7px 7px 0;
color: #fff;
text-align: center;
line-height: 14px;
font-size: 12px;
}
} }
.more { .more {
...@@ -349,14 +364,17 @@ ...@@ -349,14 +364,17 @@
.isbuy { .isbuy {
display: inline-block; display: inline-block;
margin-top: 15px; margin-top: 15px;
width: 61px; color: $active;
height: 18px; font-size: 15px;
background-color: $bg_active;
border-radius: 9px;
color: $white;
font-size: 12px;
text-align: center; text-align: center;
line-height: 18px; line-height: 18px;
font-family: PingFang SC;
font-weight: 400;
}
.free {
color: $red;
font-size: 15px;
} }
} }
...@@ -511,7 +529,7 @@ ...@@ -511,7 +529,7 @@
text-align: center; text-align: center;
height: 47px; height: 47px;
button,a { button, a {
width: 60px; width: 60px;
height: 27px; height: 27px;
background-color: $bg_active; background-color: $bg_active;
...@@ -524,7 +542,8 @@ ...@@ -524,7 +542,8 @@
margin-left: -30px; margin-left: -30px;
bottom: 10px; bottom: 10px;
} }
a{
a {
width: 90px; width: 90px;
line-height: 27px; line-height: 27px;
margin-left: -45px; margin-left: -45px;
...@@ -740,9 +759,91 @@ ...@@ -740,9 +759,91 @@
// //.is-visible { // //.is-visible {
// // background-image: none; // // background-image: none;
// //} // //}
.limit-free {
padding: 0 15px;
color: #333;
h2 {
display: flex;
align-items: center;
margin: 15px 0;
font-size: 15px;
}
.hot {
display: inline-block;
width: 25px;
height: 14px;
margin-left: 5px;
background: rgba(255, 64, 0, 1);
border-radius: 7px 7px 7px 0;
color: #fff;
text-align: center;
line-height: 14px;
font-size: 12px;
}
ul {
display: flex;
flex-wrap: wrap;
li {
margin-right: 15px;
margin-top: 0;
margin-bottom: 20px;
}
& li:nth-child(2n) {
margin-right: 0;
}
}
.origin-price {
color: #999;
font-size: 12px;
text-decoration: line-through;
}
.bottom {
margin-top: 5px;
span {
margin-right: 5px;
}
span:nth-child(3) {
margin-right: 0;
}
}
$red: #FF2121;
.bottom span:nth-child(1), .bottom button:nth-child(1) {
margin-right: 6px;
}
.current-price, .free {
color: $red;
font-size: 15px;
}
button {
width: 61px;
height: 18px;
background: rgba(0, 153, 255, 1);
border-radius: 9px;
text-align: center;
color: #fff;
font-size: 12px;
-webkit-appearance: none;
outline: 0;
border: 0;
}
}
} }
.index-box + .nav-bar + .year19-index{ .index-box + .nav-bar + .year19-index {
display: none; display: none;
} }
......
...@@ -10,160 +10,160 @@ import { StickyContainer, Sticky } from "react-sticky"; ...@@ -10,160 +10,160 @@ import { StickyContainer, Sticky } from "react-sticky";
function stopScroll(e) { function stopScroll(e) {
e.preventDefault() e.preventDefault()
} }
@connect(({user}) => ({ @connect(({user}) => ({
user user
})) }))
class Classify extends Component { class Classify extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
ispull: false, ispull: false,
display: 'none', display: 'none',
arr: [{basics: []}, {advanced: []}], arr: [{basics: []}, {advanced: []}],
allClass: [], allClass: [],
data: [], data: [],
activeTab: decodeURIComponent(getParam('name')), activeTab: decodeURIComponent(getParam('name')),
isLoading: true, isLoading: true,
top: 44 top: 44
}
} }
componentDidMount() { }
this.getTabs()
this.getList()
const el = document.querySelector('.search-nav'); componentDidMount() {
this.setState({ this.getTabs()
top: el.offsetHeight this.getList()
});
}
componentWillUnmount() { const el = document.querySelector('.search-nav');
document.removeEventListener('touchmove', stopScroll) this.setState({
} top: el.offsetHeight
});
}
componentWillUnmount() {
document.removeEventListener('touchmove', stopScroll)
}
// 获取tabs接口
getTabs = () => {
let data = 0
http.get(`${API.home}/m/course/classify/${data}`)
.then((res) => {
const _this = this
if (res.data.code === 200) {
if (res.data.data.common.length > 0) {
let arr = ['basics', 'advanced']
let arr2 = [{basics: []}, {advanced: []}]
let arr3 = []
arr.forEach(function (item, index) {
arr2[item] = res.data.data.common[index]
res.data.data.common[index].list.forEach(function (item, index) {
arr3.push({'title': item.c_name, 'id': item.c_id})
})
})
_this.setState({
arr: arr2,
allClass: arr3
})
}
} else {
Toast.info(res.data.msg, 2)
}
// 获取tabs接口
getTabs = () => {
let data = 0
http.get(`${API.home}/m/course/classify/${data}`)
.then((res) => {
const _this = this
if (res.data.code === 200) {
if (res.data.data.common.length > 0) {
let arr = ['basics', 'advanced']
let arr2 = [{basics: []}, {advanced: []}]
let arr3 = []
arr.forEach(function (item, index) {
arr2[item] = res.data.data.common[index]
res.data.data.common[index].list.forEach(function (item, index) {
arr3.push({'title': item.c_name, 'id': item.c_id})
})
}) })
.catch(err => { _this.setState({
console.log(err) arr: arr2,
allClass: arr3
}) })
} }
} else {
Toast.info(res.data.msg, 2)
}
// 获取课程接口 })
getList = () => { .catch(err => {
const _this = this console.log(err)
_this.setState((state, props)=>({ })
isLoading: true }
}));
http.get(`${API.home}/m/course/list/${getParam('id')}`).then((res) => { // 获取课程接口
if (res.data.code === 200) { getList = () => {
_this.setState({ const _this = this
data: res.data.data, _this.setState((state, props) => ({
isLoading: false isLoading: true
}) }));
} http.get(`${API.home}/m/course/list/${getParam('id')}`).then((res) => {
if (res.data.code === 200) {
_this.setState({
data: res.data.data,
isLoading: false
}) })
} }
})
}
// 点击横向滚动tab查询 // 点击横向滚动tab查询
ontabclick = (tab) => { ontabclick = (tab) => {
this.props.history.push(`/courselist?id=${tab.id}&name=${tab.title}`) this.props.history.push(`/courselist?id=${tab.id}&name=${tab.title}`)
this.getList() this.getList()
this.setState({ this.setState({
activeTab: decodeURIComponent(getParam('name')) activeTab: decodeURIComponent(getParam('name'))
}); });
} }
// 上下展示 // 上下展示
pulldown = () => { pulldown = () => {
this.setState(status => ({ this.setState(status => ({
ispull: !status.ispull, ispull: !status.ispull,
display: status.ispull ? 'none' : 'block' display: status.ispull ? 'none' : 'block'
}), () => { }), () => {
this.state.ispull ? document.addEventListener('touchmove', stopScroll, { this.state.ispull ? document.addEventListener('touchmove', stopScroll, {
passive: false passive: false
}) : document.removeEventListener('touchmove', stopScroll) }) : document.removeEventListener('touchmove', stopScroll)
}); });
} }
// 弹窗里面tab点击查询 // 弹窗里面tab点击查询
labelclick = (item) => { labelclick = (item) => {
this.props.history.push(`/courselist?id=${item.c_id}&name=${item.c_name}`) this.props.history.push(`/courselist?id=${item.c_id}&name=${item.c_name}`)
this.getList() this.getList()
this.setState(status => ({ this.setState(status => ({
ispull: !status.ispull, ispull: !status.ispull,
display: status.ispull ? 'none' : 'block', display: status.ispull ? 'none' : 'block',
activeTab: decodeURIComponent(getParam('name')) activeTab: decodeURIComponent(getParam('name'))
})) }))
} }
toCourseDetail = (id) => { toCourseDetail = (id) => {
const {dispatch, history} = this.props; const {dispatch, history} = this.props;
// dispatch(getCourses(id, () => { // dispatch(getCourses(id, () => {
history.push(`/detail?id=${id}`) history.push(`/detail?id=${id}`)
// })); // }));
} }
toClassify = () => { toClassify = () => {
this.props.history.replace('/classify'); this.props.history.replace('/classify');
} }
render() { render() {
const {user = {}} = this.props; const {user = {}} = this.props;
let isLogin = user.data && user.data.uid ? true : false; let isLogin = user.data && user.data.uid ? true : false;
const bottom = ( const bottom = (
<i className={'iconfont iconiconfront-69 pull-down'}></i> <i className={'iconfont iconiconfront-69 pull-down'}></i>
) )
const top = ( const top = (
<i className={'iconfont iconiconfront-71 pull-down'}></i> <i className={'iconfont iconiconfront-71 pull-down'}></i>
) )
let page = this.state.allClass.findIndex((item) => item.title === this.state.activeTab) let page = this.state.allClass.findIndex((item) => item.title === this.state.activeTab)
return ( return (
<div className='class-child'> <div className='class-child'>
<HeaderSearch <HeaderSearch
isLogin={isLogin} isLogin={isLogin}
toHref={this.toClassify} toHref={this.toClassify}
/> />
<Loading isLoading={this.state.isLoading}> <Loading isLoading={this.state.isLoading}>
<div className='class-content'> <div className='class-content'>
{/* <WhiteSpace/> */} {/* <WhiteSpace/> */}
<div onClick={this.pulldown.bind(this)}> <div onClick={this.pulldown.bind(this)}>
{this.state.ispull ? top : bottom} {this.state.ispull ? top : bottom}
</div> </div>
<StickyContainer> <StickyContainer>
{/* <Tabs {/* <Tabs
tabs={this.state.allClass} tabs={this.state.allClass}
animated={false} animated={false}
page={page} page={page}
...@@ -172,113 +172,148 @@ class Classify extends Component { ...@@ -172,113 +172,148 @@ class Classify extends Component {
<Tabs.DefaultTabBar {...props}/> <Tabs.DefaultTabBar {...props}/>
</div>} </div>}
> */} > */}
<Tabs <Tabs
tabs={this.state.allClass} tabs={this.state.allClass}
animated={false} animated={false}
page={page} page={page}
onChange={(tab) => this.ontabclick(tab)} onChange={(tab) => this.ontabclick(tab)}
renderTabBar={props => { renderTabBar={props => {
return ( return (
<Sticky> <Sticky>
{({ style }) => { {({style}) => {
return ( return (
<div style={{ ...style, top: `${this.state.top}px`, zIndex: 1 }}> <div style={{...style, top: `${this.state.top}px`, zIndex: 1}}>
<Tabs.DefaultTabBar {...props} /> <Tabs.DefaultTabBar {...props} />
</div> </div>
) )
}} }}
</Sticky> </Sticky>
) )
}} }}
> >
<div className='tabs'> <div className='tabs'>
<ul> <ul>
{this.state.data && this.state.data.length > 0 && this.state.data.map((item, index) => { {this.state.data && this.state.data.length > 0 && this.state.data.map((item, index) => {
const Info = ( const Info = (
<div className="info"> <div className="info">
<p className='title' <p className='title'
onClick={() => this.toCourseDetail(item.course_id)}> onClick={() => this.toCourseDetail(item.course_id)}>
{item.course_title} {item.course_title}
</p> </p>
<p className='contact text-overflow-2'>{item.desc}</p> <p className='contact text-overflow-2'>{item.desc}</p>
<div className='des'> <div className='des'>
{!item.is_buy && <p className="course-price"> {
<span className="new">¥{item.price1}</span> item.is_restricted ?
<span className="old">¥{item.price0}</span> <LimitFree course={item}/>
</p> : item.is_buy
} ? <span className="isbuy">已购买</span>
{item.is_buy && : <p className="course-price">
<span className="isbuy">已购买</span> <span className="new">¥{item.price1}</span>
} <span className="old">¥{item.price0}</span>
</div> </p>
</div> }
) </div>
const status = ( </div>
!item.is_buy && )
<div> const status = (
{item.bargain_num === 0 && item.groupon_num !== 0 && !item.is_buy &&
<p className='course-status'>拼团减{item.groupon_num}</p> <div>
} {item.bargain_num === 0 && item.groupon_num !== 0 &&
{item.bargain_num !== 0 && item.groupon_num === 0 && <p className='course-status'>拼团减{item.groupon_num}</p>
<p className='course-status'>砍价减{item.bargain_num}</p> }
} {item.bargain_num !== 0 && item.groupon_num === 0 &&
{ <p className='course-status'>砍价减{item.bargain_num}</p>
item.is_aist && <span className='return_cash'></span> }
} {
</div> item.is_aist && <span className='return_cash'></span>
) }
return ( </div>
<VList )
key={index} return (
status={status} <VList
img={item.image_name} key={index}
id={item.course_id} status={status}
info={Info} img={item.image_name}
toDetail={this.toCourseDetail} id={item.course_id}
/> info={Info}
) toDetail={this.toCourseDetail}
})} />
</ul> )
</div> })}
</Tabs> </ul>
</div>
</Tabs>
</StickyContainer> </StickyContainer>
<WhiteSpace/> <WhiteSpace/>
</div> </div>
<div className='mbc-box' style={{display: this.state.display}}> <div className='mbc-box' style={{display: this.state.display}}>
{ {
this.state.arr.basics && this.state.arr.basics &&
<div className="tabcontent"> <div className="tabcontent">
<ClassCourse activeTab={this.state.activeTab} data={this.state.arr.basics.list} <ClassCourse activeTab={this.state.activeTab} data={this.state.arr.basics.list}
title={this.state.arr.basics.name} labelclick={this.labelclick}/> title={this.state.arr.basics.name} labelclick={this.labelclick}/>
<ClassCourse activeTab={this.state.activeTab} data={this.state.arr.advanced.list} <ClassCourse activeTab={this.state.activeTab} data={this.state.arr.advanced.list}
title={this.state.arr.advanced.name} labelclick={this.labelclick}/> title={this.state.arr.advanced.name} labelclick={this.labelclick}/>
</div> </div>
} }
</div> </div>
</Loading> </Loading>
</div> </div>
) )
} }
} }
function ClassCourse(props) { function ClassCourse(props) {
return ( return (
<div className="class-course"> <div className="class-course">
<p className='course-items-title'>{props.title}</p> <p className='course-items-title'>{props.title}</p>
<div className='items-box'> <div className='items-box'>
{ {
props.data && props.data.length > 0 && props.data.map((item, index) => { props.data && props.data.length > 0 && props.data.map((item, index) => {
return ( return (
<span className={props.activeTab === item.c_name ? 'active-label' : 'item-label'} <span className={props.activeTab === item.c_name ? 'active-label' : 'item-label'}
key={index} onClick={e => props.labelclick(item)}>{item.c_name}</span> key={index} onClick={e => props.labelclick(item)}>{item.c_name}</span>
) )
}) })
} }
</div> </div>
</div> </div>
) )
}
function LimitFreeStatus({course}) {
/*
* limit-free-status: 0-未领取 1-已领取 2-已过期
*
* */
switch (course.limit_free_status) {
case 0:
return <div className="limit-free">
<span>限时免费</span>
<span>¥{course.price0}</span>
</div>
case 1:
return <div>已领取</div>
case 2:
return <p className="course-price">
<span className="new">¥{course.price1}</span>
<span className="old">¥{course.price0}</span>
</p>
}
}
function LimitFree({course}) {
if (course.is_buy) {
if (course.limit_free_status === 1) {
return <div className={'isbuy'}>已领取</div>
} else {
return <div className={'isbuy'}>已购买</div>
}
} else {
return <LimitFreeStatus course={course}/>
}
} }
export default Classify; export default Classify;
html,body,#root { html, body, #root {
height: 100%; height: 100%;
} }
.class-child { .class-child {
position: relative; position: relative;
height: 100%; height: 100%;
.preferential{ .preferential {
width: 100%; width: 100%;
height: 44px; height: 44px;
position: fixed; position: fixed;
...@@ -20,7 +21,7 @@ html,body,#root { ...@@ -20,7 +21,7 @@ html,body,#root {
// padding: 88px 12px 0; // padding: 88px 12px 0;
position: relative; position: relative;
.custom-render-bar{ .custom-render-bar {
position: fixed; position: fixed;
top: 43px; top: 43px;
left: 0; left: 0;
...@@ -51,6 +52,7 @@ html,body,#root { ...@@ -51,6 +52,7 @@ html,body,#root {
background-color: rgba(224, 46, 36, 0.6); background-color: rgba(224, 46, 36, 0.6);
} }
.return_cash { .return_cash {
position: absolute; position: absolute;
width: 31px; width: 31px;
...@@ -103,14 +105,23 @@ html,body,#root { ...@@ -103,14 +105,23 @@ html,body,#root {
.isbuy { .isbuy {
display: inline-block; display: inline-block;
width: 61px; color: #09f;
height: 18px; font-size: 15px;
background-color: $bg_active;
border-radius: 9px;
color: $white;
font-size: 12px;
text-align: center; text-align: center;
line-height: 18px; }
.limit-free {
span:first-child {
color: #FF2121;
font-size: 15px;
margin-right: 10px;
}
span:last-child {
color: #999;
font-size: 11px;
text-decoration: line-through;
}
} }
} }
} }
...@@ -120,6 +131,7 @@ html,body,#root { ...@@ -120,6 +131,7 @@ html,body,#root {
display: flex; display: flex;
margin-top: 10px; margin-top: 10px;
margin-bottom: 50px; margin-bottom: 50px;
ul { ul {
width: 100%; width: 100%;
} }
...@@ -136,6 +148,7 @@ html,body,#root { ...@@ -136,6 +148,7 @@ html,body,#root {
background-color: $bg_fff; background-color: $bg_fff;
color: $color_666; color: $color_666;
} }
.am-tabs-tab-bar-wrap { .am-tabs-tab-bar-wrap {
padding-right: 20px; padding-right: 20px;
} }
...@@ -216,6 +229,7 @@ html,body,#root { ...@@ -216,6 +229,7 @@ html,body,#root {
margin-bottom: -5px; margin-bottom: -5px;
font-size: 12px; font-size: 12px;
} }
.active-label { .active-label {
display: inline-block; display: inline-block;
width: 30.5%; width: 30.5%;
...@@ -234,8 +248,9 @@ html,body,#root { ...@@ -234,8 +248,9 @@ html,body,#root {
} }
} }
} }
.am-tabs-default-bar-top .am-tabs-default-bar-tab::after { .am-tabs-default-bar-top .am-tabs-default-bar-tab::after {
background-color: $bg_fff!important; background-color: $bg_fff !important;
} }
} }
...@@ -11,540 +11,565 @@ import BargainConfirmBind from './../bindPhone/confirm'; ...@@ -11,540 +11,565 @@ import BargainConfirmBind from './../bindPhone/confirm';
import Mask from '@/common/Mask/index'; import Mask from '@/common/Mask/index';
class BtnStatus extends Component { class BtnStatus extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
isbuy: 1, isbuy: 1,
is_baoming: 0, is_baoming: 0,
group_status: 3, group_status: 3,
in_cart: false, in_cart: false,
countdown: 0, countdown: 0,
barInfo: {}, barInfo: {},
bindPhone: false, bindPhone: false,
bindConfrm: false, bindConfrm: false,
bindInfo: {}, // 冲突信息 bindInfo: {}, // 冲突信息
formInfo: {}, formInfo: {},
}
} }
}
componentDidMount() {
// this.getBargainInfo() componentDidMount() {
this.group = false; // this.getBargainInfo()
this.group = false;
}
// componentDidUpdate(prevProps) {
// let {courseInfo} = this.props
// let {courseInfo: prevCourseInfo} = prevProps
// if (courseInfo && courseInfo.is_bargain) {
// if (prevCourseInfo && courseInfo.is_bargain !== prevCourseInfo.is_bargain) {
// this.getBargainInfo()
// }
// }
// }
componentWillReceiveProps(nextProps) {
const {data = {}, user = {}} = nextProps;
if (data.is_bargain && user.data && user.data.uid) {
this.getBargainInfo();
} }
// if(nextProps.data && nextProps.data.is_bargain) {
// this.getBargainInfo()
// componentDidUpdate(prevProps) {
// let {courseInfo} = this.props
// let {courseInfo: prevCourseInfo} = prevProps
// if (courseInfo && courseInfo.is_bargain) {
// if (prevCourseInfo && courseInfo.is_bargain !== prevCourseInfo.is_bargain) {
// this.getBargainInfo()
// }
// }
// } // }
this.setState({
componentWillReceiveProps(nextProps) { courseInfo: data,
const { data = {}, user = {}} = nextProps; countdown: nextProps.countdown,
if(data.is_bargain && user.data && user.data.uid) { });
this.getBargainInfo(); }
// // 加入购物车 type:1 加入购物车,2加入购物车并跳转到购物车页面去支付
// toCart = (type) => {
// const { history, addCourseToCart } = this.props;
// let data = {
// course_id: getParam('id')
// };
// http.post(`${API.home}/m/cart/add`, data).then((res) => {
// if (res.data.code === 200) {
// if (type === 1) {
// Toast.info('已加入购物车', 2)
// // this.props.getCourses()
// // document.location.reload()
// addCourseToCart();
// } else {
// history.replace('/shopcart');ß
// }
// } else if (res.data.code === 15001) {
// history.replace('/shopcart');
// } else if (res.data.code === 4030) {
// history.replace('/passport');
// } else {
// Toast.info(res.data.msg, 2);
// }
// })
// };
// 返现课程的立即购买
signUpNow = () => {
if (this.props.user.hasError) {
// 未登录 去登陆
this.props.history.push('/passport');
} else {
let cidArr = JSON.stringify([Number(getParam('id'))]);
http.get(`${API['base-api']}/m/cart/addtopreorder/${cidArr}?type=1`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push("/order?id=" + res.data.data[0], {type: 1});
} else {
Toast.info(res.data.msg, 2);
} }
// if(nextProps.data && nextProps.data.is_bargain) { })
// this.getBargainInfo()
// }
this.setState({
courseInfo: data,
countdown: nextProps.countdown,
});
} }
};
// // 加入购物车 type:1 加入购物车,2加入购物车并跳转到购物车页面去支付
// toCart = (type) => { // 普通课程的立即报名 要模拟结算过程
// const { history, addCourseToCart } = this.props; simpleCourse = () => {
// let data = { if (this.props.user.hasError) {
// course_id: getParam('id') // 未登录 去登陆
// }; this.props.history.push('/passport');
// http.post(`${API.home}/m/cart/add`, data).then((res) => { } else {
// if (res.data.code === 200) { http.get(`${API['base-api']}/m/cart/addtopreorder/[${getParam('id')}]`).then((res) => {
// if (type === 1) { if (res.data.errno === 0) {
// Toast.info('已加入购物车', 2) this.props.history.push(`/order?id=${getParam('id')}`, {simple: 1})
// // this.props.getCourses()
// // document.location.reload()
// addCourseToCart();
// } else {
// history.replace('/shopcart');ß
// }
// } else if (res.data.code === 15001) {
// history.replace('/shopcart');
// } else if (res.data.code === 4030) {
// history.replace('/passport');
// } else {
// Toast.info(res.data.msg, 2);
// }
// })
// };
// 返现课程的立即购买
signUpNow = () => {
if(this.props.user.hasError) {
// 未登录 去登陆
this.props.history.push('/passport');
}else{
let cidArr = JSON.stringify([Number(getParam('id'))]);
http.get(`${API['base-api']}/m/cart/addtopreorder/${cidArr}?type=1`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push("/order?id=" + res.data.data[0], {type: 1});
} else {
Toast.info(res.data.msg, 2);
}
})
}
};
// 普通课程的立即报名 要模拟结算过程
simpleCourse = () => {
if(this.props.user.hasError) {
// 未登录 去登陆
this.props.history.push('/passport');
}else{
http.get(`${API['base-api']}/m/cart/addtopreorder/[${getParam('id')}]`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push(`/order?id=${getParam('id')}`, {simple: 1})
} else {
Toast.info(res.data.msg, 2);
}
})
}
};
// 格式化开课时间
formatDate = (date) => {
let ary = date.split('-');
return `${ary[1]}${ary[2]}日开课`;
};
// 直接购买
tobuy = () => {
const {user} = this.props;
const {barInfo} = this.state;
const uid = user && user.data && user.data.uid
if (!uid) {
this.props.history.push('/passport/login')
} else { } else {
if (barInfo.bargain_status === 2) { Toast.info(res.data.msg, 2);
// this.toCart(2)
// 新需求 不需要加入购物车 直接走普通课程的立即报名流程 跳到订单页
this.simpleCourse();
} else {
// 取消砍价记录
this.setState({
isShowOverlay: true,
bargainStatus: 1,
})
}
}
};
// 一键开团
keyToGroup = () => {
if(this.props.user.hasError) {
// 未登录 去登陆
this.props.history.push('/passport');
return;
}
this.props.history.push(`/order?id=${getParam('id')}`, {group: 1})
};
// 砍完价去支付
bargainToOrder = () => {
if(this.props.user.hasError) {
// 未登录 去登陆
this.props.history.push('/passport');
}else{
http.get(`${API['base-api']}/m/cart/addtopreorder/[${getParam('id')}]`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push(`/order?id=[${getParam('id')}]`, {bargain: 1});
} else {
Toast.info(res.data.msg, 2);
}
})
} }
}; })
// 取消砍价
cancel = () => {
let data = {
courseId: getParam('id')
}
http.post(`${API.home}/m/bargain/cancel`, data).then((res) => {
if (res.data.code === 200) {
this.setState({
isShowOverlay: false,
bargainStatus: '',
})
http.get(`${API['base-api']}/m/cart/addtopreorder/[${getParam('id')}]`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push(`/order?id=[${getParam('id')}]`, {simple: 1});
} else {
Toast.info(res.data.msg, 2);
}
})
// window.location.href = '/shopcart'
// this.props.history.push(`/order?id=[${getParam('id')}]`, {simple: 1})
} else {
Toast.info(res.data.msg, 2)
}
})
} }
};
close = () => {
// 格式化开课时间
formatDate = (date) => {
let ary = date.split('-');
return `${ary[1]}${ary[2]}日开课`;
};
// 直接购买
tobuy = () => {
const {user} = this.props;
const {barInfo} = this.state;
const uid = user && user.data && user.data.uid
if (!uid) {
this.props.history.push('/passport/login')
} else {
if (barInfo.bargain_status === 2) {
// this.toCart(2)
// 新需求 不需要加入购物车 直接走普通课程的立即报名流程 跳到订单页
this.simpleCourse();
} else {
// 取消砍价记录
this.setState({ this.setState({
isShowOverlay: false, isShowOverlay: true,
bargainStatus: '', bargainStatus: 1,
}) })
}
} }
// 砍价接口 };
toKanjia = () => {
const {user, history} = this.props; // 一键开团
const uid = user && user.data && user.data.uid; keyToGroup = () => {
const course_id = getParam('id'); if (this.props.user.hasError) {
if (!uid) { // 未登录 去登陆
this.props.history.push('/passport/login') this.props.history.push('/passport');
return;
}
this.props.history.push(`/order?id=${getParam('id')}`, {group: 1})
};
// 砍完价去支付
bargainToOrder = () => {
if (this.props.user.hasError) {
// 未登录 去登陆
this.props.history.push('/passport');
} else {
http.get(`${API['base-api']}/m/cart/addtopreorder/[${getParam('id')}]`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push(`/order?id=[${getParam('id')}]`, {bargain: 1});
} else { } else {
let data = { Toast.info(res.data.msg, 2);
course_id,
type: 1, // 1 用户自己砍价 2 使用砍价神器 3 好友助力砍价 4 好友第二次助力
parent_uid: 0 // 被助力人id 【自己本人操作传0】
}
http.post(`${API.home}/m/bargain/toBargain`, data).then((res) => {
const {data, code, msg} = res.data;
if (code === 200) {
// user_status 用户状态 1-关注公众号,2-绑定手机号 3-再砍一刀 (是发起人没有这个字段)
if(data.user_status === 2) {
this.setState({
bindPhone: true
})
}else {
history.push(`/bargain-middle-page?id=${course_id}&bargaincode=${data.bargain_code}&is_originator=1`)
}
} else {
Toast.info(msg, 2)
}
})
} }
})
} }
};
// 开始学习 // 取消砍价
toStudy=(vCourseId,isHaveVideo)=>{ cancel = () => {
const { history } = this.props; let data = {
if(isHaveVideo == 0){ courseId: getParam('id')
Toast.info('尚未开课,开课后立即上传课程~', 2) }
http.post(`${API.home}/m/bargain/cancel`, data).then((res) => {
if (res.data.code === 200) {
this.setState({
isShowOverlay: false,
bargainStatus: '',
})
http.get(`${API['base-api']}/m/cart/addtopreorder/[${getParam('id')}]`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push(`/order?id=[${getParam('id')}]`, {simple: 1});
} else {
Toast.info(res.data.msg, 2);
}
})
// window.location.href = '/shopcart'
// this.props.history.push(`/order?id=[${getParam('id')}]`, {simple: 1})
} else {
Toast.info(res.data.msg, 2)
}
})
}
close = () => {
this.setState({
isShowOverlay: false,
bargainStatus: '',
})
}
// 砍价接口
toKanjia = () => {
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
const course_id = getParam('id');
if (!uid) {
this.props.history.push('/passport/login')
} else {
let data = {
course_id,
type: 1, // 1 用户自己砍价 2 使用砍价神器 3 好友助力砍价 4 好友第二次助力
parent_uid: 0 // 被助力人id 【自己本人操作传0】
}
http.post(`${API.home}/m/bargain/toBargain`, data).then((res) => {
const {data, code, msg} = res.data;
if (code === 200) {
// user_status 用户状态 1-关注公众号,2-绑定手机号 3-再砍一刀 (是发起人没有这个字段)
if (data.user_status === 2) {
this.setState({
bindPhone: true
})
} else {
history.push(`/bargain-middle-page?id=${course_id}&bargaincode=${data.bargain_code}&is_originator=1`)
}
} else { } else {
history.push(`/play/video?id=${vCourseId}`) Toast.info(msg, 2)
} }
})
} }
}
//获取砍价信息
getBargainInfo = () => { // 开始学习
const {user} = this.props toStudy = (vCourseId, isHaveVideo) => {
const uid = user && user.data && user.data.uid const {history} = this.props;
let data = { if (isHaveVideo == 0) {
courseId: getParam('id') Toast.info('尚未开课,开课后立即上传课程~', 2)
} } else {
http.post(`${API.home}/m/bargain/courseDetail`, data).then((res) => { history.push(`/play/video?id=${vCourseId}`)
if (res.data.code === 200) { }
this.setState({ }
barInfo: res.data.data
}) //获取砍价信息
} else { getBargainInfo = () => {
Toast.info(res.data.msg, 2) const {user} = this.props
} const uid = user && user.data && user.data.uid
}) let data = {
courseId: getParam('id')
} }
http.post(`${API.home}/m/bargain/courseDetail`, data).then((res) => {
if (res.data.code === 200) {
this.setState({
barInfo: res.data.data
})
} else {
Toast.info(res.data.msg, 2)
}
})
}
// 付定金 付尾款
expandPay = (info, type) => {
// type 等于1是定金 等于2是尾款
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
if (type == 1) {
this.props.history.push(
`/deposit-order?oid=${getParam('id')}&source=${1}`,
{
id: getParam('id'),
isexpand: 1,
sourcenum: 1
}
)
} else {
let timeStamp = Date.parse(new Date()) / 1000;
if (timeStamp >= info.start_timestamp) {
this.props.history.push(
'/final-deposit-order?source=1',
{
id: getParam('id'),
sourcenum: 1
// 付定金 付尾款
expandPay = (info,type)=>{
// type 等于1是定金 等于2是尾款
const {user, history} = this.props;
const uid = user && user.data && user.data.uid;
if (!uid) {
this.props.history.push('/passport/login')
} else {
if(type == 1){
this.props.history.push(
`/deposit-order?oid=${getParam('id')}&source=${1}`,
{
id: getParam('id'),
isexpand: 1,
sourcenum: 1
}
)
} else {
let timeStamp = Date.parse(new Date()) / 1000;
if (timeStamp >= info.start_timestamp) {
this.props.history.push(
'/final-deposit-order?source=1',
{
id: getParam('id'),
sourcenum: 1
}
)
} else {
Toast.info("付尾款时间将在" + info.final_start_time + "开启",2);
}
} }
)
} else {
Toast.info("付尾款时间将在" + info.final_start_time + "开启", 2);
} }
}
} }
}
// 隐藏弹窗
handleToHide = (key) => {
this.setState({
[key]: false
});
}
// 绑定手机号 -- 确认
confirmBindPhone = (params, bindInfo) => {
this.setState({
bindPhone: false,
bindConfrm: true,
formInfo: params,
bindInfo
});
}
qimoChatClick = () => {
qimoChatClick()
}
render() {
// data 课程信息;barInfo 砍价信息
const {user = {}, toCart, country} = this.props;
const {
countdown,
barInfo,
courseInfo: info = {},
bindPhone,
bindConfrm,
bindInfo,
formInfo,
} = this.state;
const uid = user.data && user.data.uid;
return (
<div>
{/* 绑定手机号 */}
<Mask visible={bindPhone} handleToHide={() => this.handleToHide('bindPhone')}>
<BindPhone
country={country}
handleToBargain={this.toKanjia}
confirmBindPhone={this.confirmBindPhone}
/>
</Mask>
{/* 绑定手机号--确认 */}
<Mask visible={bindConfrm} handleToHide={() => this.handleToHide('bindConfrm')}>
<BargainConfirmBind
data={formInfo}
bindInfo={bindInfo}
handleToHide={() => this.handleToHide('bindConfrm')}
handleToBargain={this.toKanjia}
/>
</Mask>
{/*正常购买*/}
{
info.is_baoming === 0 && info.group_status !== 3 &&
<div className='btns-box'>
<a className='consult consult-s' onClick={() => this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
{
info.in_cart &&
<Link to='/shopcart' className='btn btn-s bg-FCCD05'>去购物车结算</Link>
}
{
!info.in_cart &&
<button className='btn btn-s bg-FCCD05' onClick={e => toCart(1)}>加入购物车</button>
// 隐藏弹窗 }
handleToHide = (key) => { <span className='btn btn-s bg-FD7700' onClick={e => this.simpleCourse()}>立即报名</span>
console.log(key); </div>
this.setState({ }
[key]: false
});
}
// 绑定手机号 -- 确认 {/* 定金课程 is_deposit 是否定金课程 0-否 1-付定金 2-付尾款*/}
confirmBindPhone = (params, bindInfo) => { {
this.setState({ info.is_baoming === 0 && info.is_deposit != 0 &&
bindPhone: false, <div className='btns-box'>
bindConfrm: true, <a className='consult consult-m' onClick={() => this.qimoChatClick()}>
formInfo: params, <i className='iconfont iconerji'/>
bindInfo <span>课程咨询</span>
}); </a>
} <div className='btn btn-m bg-FD7700' onClick={() => this.expandPay(info.deposit_info, info.is_deposit)}>
{info.is_deposit == 1 ? '立即付定金' : '立即付尾款'}
</div>
</div>
}
qimoChatClick=()=>{ {/*已购买*/}
qimoChatClick() {
} info.is_baoming === 1 &&
render() { <div className='btns-box'>
// data 课程信息;barInfo 砍价信息 <a className='consult consult-m' onClick={() => this.qimoChatClick()}>
const { user = {}, toCart, country } = this.props; <i className='iconfont iconerji'/>
const { <span>课程咨询</span>
countdown, </a>
barInfo, <a className='btn btn-m bg-09f' onClick={() => this.toStudy(info.v_course_id, info.is_have_video)}>
courseInfo: info = {}, 开始学习
bindPhone, </a>
bindConfrm, </div>
bindInfo, }
formInfo, {/*拼团 未开团*/}
} = this.state; {
const uid = user.data && user.data.uid; info.is_baoming === 0 && info.group_status === 3 &&
return ( <div className='btns-box'>
<div> <a className='consult consult-s' onClick={() => this.qimoChatClick()}>
{/* 绑定手机号 */} <i className='iconfont iconerji'></i>
<Mask visible={bindPhone} handleToHide={() => this.handleToHide('bindPhone')}> <span>课程咨询</span>
<BindPhone </a>
country={country} <button className='btn btn-s bg-F4AAA7' onClick={this.simpleCourse}>
handleToBargain={this.toKanjia} <span>{${info.price1}`}</span>
confirmBindPhone={this.confirmBindPhone} <span>直接购买</span>
/> </button>
</Mask> <button className='btn btn-s bg-E02E24'>
{/* 绑定手机号--确认 */}
<Mask visible={bindConfrm} handleToHide={() => this.handleToHide('bindConfrm')}>
<BargainConfirmBind
data={formInfo}
bindInfo={bindInfo}
handleToHide={() => this.handleToHide('bindConfrm')}
handleToBargain={this.toKanjia}
/>
</Mask>
{/*正常购买*/}
{
info.is_baoming === 0 && info.group_status !== 3 &&
<div className='btns-box'>
<a className='consult consult-s' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
{
info.in_cart &&
<Link to='/shopcart' className='btn btn-s bg-FCCD05'>去购物车结算</Link>
}
{
!info.in_cart &&
<button className='btn btn-s bg-FCCD05' onClick={e => toCart(1)}>加入购物车</button>
}
<span className='btn btn-s bg-FD7700' onClick={e => this.simpleCourse()}>立即报名</span>
</div>
}
{/* 定金课程 is_deposit 是否定金课程 0-否 1-付定金 2-付尾款*/}
{
info.is_baoming === 0 && info.is_deposit != 0 &&
<div className='btns-box'>
<a className='consult consult-m' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji' />
<span>课程咨询</span>
</a>
<div className='btn btn-m bg-FD7700' onClick={()=>this.expandPay(info.deposit_info,info.is_deposit)}>
{info.is_deposit == 1 ? '立即付定金':'立即付尾款'}
</div>
</div>
}
{/*已购买*/}
{
info.is_baoming === 1 &&
<div className='btns-box'>
<a className='consult consult-m' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji' />
<span>课程咨询</span>
</a>
<a className='btn btn-m bg-09f' onClick={() => this.toStudy(info.v_course_id,info.is_have_video)}>
开始学习
</a>
</div>
}
{/*拼团 未开团*/}
{
info.is_baoming === 0 && info.group_status === 3 &&
<div className='btns-box'>
<a className='consult consult-s' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<button className='btn btn-s bg-F4AAA7' onClick={this.simpleCourse}>
<span>{${info.price1}`}</span>
<span>直接购买</span>
</button>
<button className='btn btn-s bg-E02E24'>
<span onClick={this.keyToGroup}> <span onClick={this.keyToGroup}>
<span>{${info.pdd_group_info.price}`}</span> <span>{${info.pdd_group_info.price}`}</span>
<span>一键开团</span> <span>一键开团</span>
</span> </span>
</button> </button>
</div> </div>
} }
{/*拼团 已开团*/} {/*拼团 已开团*/}
{ {
info.is_baoming === 0 && info.group_status === 4 && info.is_baoming === 0 && info.group_status === 4 &&
<div className='btns-box'> <div className='btns-box'>
<a className='consult consult-s' onClick={()=>this.qimoChatClick()}> <a className='consult consult-s' onClick={() => this.qimoChatClick()}>
<i className='iconfont iconerji'></i> <i className='iconfont iconerji'></i>
<span>课程咨询</span> <span>课程咨询</span>
</a> </a>
<div className='btn btn-l bg-E02E24' onClick={this.props.invitedFriends}> <div className='btn btn-l bg-E02E24' onClick={this.props.invitedFriends}>
邀请好友参团 {countdown} 后结束 邀请好友参团 {countdown} 后结束
</div>
</div>
}
{/*砍价*/}
{
info.is_baoming === 0 && this.props.data && this.props.data.is_bargain &&
<div className='btns-box'>
<a className='consult consult-s' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<button className='btn btn-s bg-F4AAA7'>
<span>¥{info.price1}</span>
<span onClick={this.tobuy}>直接购买</span>
</button>
{
(barInfo.bargain_status === 2|| (getParam('id') === '139' && barInfo.bargain_status === 3) || !uid) &&
<button className='btn btn-s bg-E02E24' onClick={this.toKanjia}>
我要砍价
</button>
}
{
(barInfo.bargain_status === 0 || barInfo.bargain_status === 1) && (uid) &&
<button className='btn btn-s bg-E02E24'>
<span>¥{barInfo.amount}</span>
<span onClick={this.bargainToOrder}>去支付</span>
</button>
}
</div>
}
{/*特殊课程*/}
{
this.state.isbuy === 20 &&
<div className='btns-box'>
<a className='consult-l' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
</div>
}
{/*特训营课程 未登录 未报名*/}
{
(info.is_aist && (this.props.user.hasError || info.is_baoming === 0)) &&
<div className='btns-box'>
<a className='consult consult-m' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<button className='btn sign-up-now' onClick={e => this.signUpNow()}>
<span>立即报名</span>
</button>
</div>
}
{/*特训营课程 登陆且已报名*/}
{
info.is_aist && !this.props.user.hasError && info.is_baoming === 1 &&
<div className='btns-box'>
<a className='consult consult-m' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
{
info.aist_start_time === "" ?
(
<a className='btn btn-m bg-09f' onClick={() => this.toStudy(info.v_course_id,info.is_have_video)}>开始学习</a>
) : (
<button className='btn btn-m wait-open' >
<span>{this.formatDate(info.aist_start_time)}</span>
</button>
)
}
</div>
}
{
this.state.isShowOverlay &&
<Overlay>
{/*引导关注公众号*/}
{
this.state.bargainStatus === 1 &&
<CancelBargain close={this.close} cancel={this.cancel}/>
}
<i onClick={this.close} className={'iconfont iconiconfront-2 bargain-close'}></i>
</Overlay>
}
</div> </div>
) </div>
} }
{/*砍价*/}
{
info.is_baoming === 0 && this.props.data && this.props.data.is_bargain &&
<div className='btns-box'>
<a className='consult consult-s' onClick={() => this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<button className='btn btn-s bg-F4AAA7'>
<span>¥{info.price1}</span>
<span onClick={this.tobuy}>直接购买</span>
</button>
{
(barInfo.bargain_status === 2 || (getParam('id') === '139' && barInfo.bargain_status === 3) || !uid) &&
<button className='btn btn-s bg-E02E24' onClick={this.toKanjia}>
我要砍价
</button>
}
{
(barInfo.bargain_status === 0 || barInfo.bargain_status === 1) && (uid) &&
<button className='btn btn-s bg-E02E24'>
<span>¥{barInfo.amount}</span>
<span onClick={this.bargainToOrder}>去支付</span>
</button>
}
</div>
}
{/*特殊课程*/}
{
this.state.isbuy === 20 &&
<div className='btns-box'>
<a className='consult-l' onClick={() => this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
</div>
}
{/*特训营课程 未登录 未报名*/}
{
(info.is_aist && (this.props.user.hasError || info.is_baoming === 0)) &&
<div className='btns-box'>
<a className='consult consult-m' onClick={() => this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<button className='btn sign-up-now' onClick={e => this.signUpNow()}>
<span>立即报名</span>
</button>
</div>
}
{/*特训营课程 登陆且已报名*/}
{
info.is_aist && !this.props.user.hasError && info.is_baoming === 1 &&
<div className='btns-box'>
<a className='consult consult-m' onClick={() => this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
{
info.aist_start_time === "" ?
(
<a className='btn btn-m bg-09f'
onClick={() => this.toStudy(info.v_course_id, info.is_have_video)}>开始学习</a>
) : (
<button className='btn btn-m wait-open'>
<span>{this.formatDate(info.aist_start_time)}</span>
</button>
)
}
</div>
}
{
this.state.isShowOverlay &&
<Overlay>
{/*引导关注公众号*/}
{
this.state.bargainStatus === 1 &&
<CancelBargain close={this.close} cancel={this.cancel}/>
}
<i onClick={this.close} className={'iconfont iconiconfront-2 bargain-close'}></i>
</Overlay>
}
{
/*
*
* limit_free_status: 0 未领取 1已领取未过期 2已过期
* */
info.is_baoming === 0 && info.is_limit_free && info.limit_free_status == 0 && <div className='btns-box'>
<a className='consult consult-m' onClick={() => this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<button className={'get-course btn'} onClick={() => {
const {history, user, getCourse} = this.props
if (user.hasError) {
history.push('/passport')
} else {
getCourse(info.course_id, info.v_course_id)
}
}}>立即领取
</button>
</div>
}
</div>
)
}
} }
function CancelBargain(props) { function CancelBargain(props) {
return ( return (
<div className='cancel-bargain'> <div className='cancel-bargain'>
<p className='top-img'><i className='iconfont icondanseshixintubiao-8'></i></p> <p className='top-img'><i className='iconfont icondanseshixintubiao-8'></i></p>
<p className='tip-mess'>您已发起砍价,直接购买将清除已砍金额。直接购买可使用优惠券~</p> <p className='tip-mess'>您已发起砍价,直接购买将清除已砍金额。直接购买可使用优惠券~</p>
<div className="btns"> <div className="btns">
<button onClick={props.close}>取消</button> <button onClick={props.close}>取消</button>
<button onClick={props.cancel}>确定</button> <button onClick={props.cancel}>确定</button>
</div> </div>
</div> </div>
) )
} }
export default connect( export default connect(
state => ({ state => ({
user: state.user user: state.user
}), }),
{getCourses} {getCourses}
)(BtnStatus) )(BtnStatus)
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
background-color: $bg_fff; background-color: $bg_fff;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
box-shadow:0px 0px 5px 0px rgba(0, 0, 0, 0.1); box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.1);
z-index: 3; z-index: 3;
.consult { .consult {
...@@ -84,18 +84,26 @@ ...@@ -84,18 +84,26 @@
font-size: 12px; font-size: 12px;
} }
} }
.sign-up-now { .sign-up-now {
width: 50%; width: 50%;
color: #fff; color: #fff;
font-size: 16px; font-size: 16px;
background: linear-gradient(270deg,rgba(255,64,0,1) 0%,rgba(253,119,0,1) 100%); background: linear-gradient(270deg, rgba(255, 64, 0, 1) 0%, rgba(253, 119, 0, 1) 100%);
} }
.learn-now { .learn-now {
background-color: #0099FF; background-color: #0099FF;
font-size: 16px; font-size: 16px;
color: #FFF; color: #FFF;
} }
.get-course {
width: 280px;
height: 44px;
background: linear-gradient(90deg, rgba(253, 119, 0, 1) 0%, rgba(255, 64, 0, 1) 100%);
}
.btn-m { .btn-m {
width: 50%; width: 50%;
} }
......
import React, {Component} from 'react' import React, { Component } from 'react'
import './index.scss' import './index.scss'
import Bargain from './bargain' import Bargain from './bargain'
import Group from './group' import Group from './group'
import OutLine from './outline' import OutLine from './outline'
import {HeaderBar, CallApp} from '../../common' import { HeaderBar, CallApp } from '../../common'
import ShareRank from "./shareRank" import ShareRank from "./shareRank"
import Audition from "./audition" import Audition from "./audition"
import Single from "./single" import Single from "./single"
...@@ -11,575 +11,613 @@ import SingleSuccess from './single/singleSuccess'; ...@@ -11,575 +11,613 @@ import SingleSuccess from './single/singleSuccess';
import BtnStatus from "./btnstatus" import BtnStatus from "./btnstatus"
import Barrage from './barrage' import Barrage from './barrage'
import Deposit from './deposit' import Deposit from './deposit'
import {connect} from "react-redux" import { connect } from "react-redux"
import {getCourses, addCourseToCart} from "./actions" import { getCourses, addCourseToCart } from "./actions"
import {getParam, http, browser, wxShare} from "@/utils" import { getParam, http, browser, wxShare } from "@/utils"
import {Toast} from 'antd-mobile' import { Toast } from 'antd-mobile'
import {bindActionCreators} from "redux"; import { bindActionCreators } from "redux";
import {delCountryNum} from './../country/countryRedux'; import { delCountryNum } from './../country/countryRedux';
import { Popup } from "@common/index"
import RedPacket from './redPacket'; import RedPacket from './redPacket';
import {Link} from "react-router-dom";
import ExpandActiveToast from "../Index/expandActiveToast"; import ExpandActiveToast from "../Index/expandActiveToast";
class Detail extends Component { class Detail extends Component {
courseId courseId
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
isbuy: 0, isbuy: 0,
isvip: 0, isvip: 0,
auditionBox: false, auditionBox: false,
singleBox: false, singleBox: false,
singleType: 1, singleType: 1,
shareRank: false, shareRank: false,
singMess: '', singMess: '',
barInfo: '', barInfo: '',
share: false, share: false,
countdown: '00:00:00', countdown: '00:00:00',
outList: [], outList: [],
list: [], list: [],
course: {}, course: {},
nowPrice: 0, nowPrice: 0,
laterPrice: 0, laterPrice: 0,
isPdd: 0, // 是否是拼团课程 控制首次单集购买后的 全集购买 接口: 拼团课程走拼团接口,否则直接走购买接口 isPdd: 0, // 是否是拼团课程 控制首次单集购买后的 全集购买 接口: 拼团课程走拼团接口,否则直接走购买接口
isRedPacket: true, isRedPacket: true,
countDownTime: '20s', countDownTime: '20s',
}
} }
}
componentDidMount() { componentDidMount() {
this.fetchCourseInfo(); this.fetchCourseInfo();
const {location: {state = {}}} = this.props; const {location: {state = {}}} = this.props;
if (state.oid) { if (state.oid) {
this.check(state.oid); this.check(state.oid);
} }
if (getParam('is_class') === 1 || getParam('weixinpay')) { if (getParam('is_class') === 1 || getParam('weixinpay')) {
this.payCallback() this.payCallback()
} }
if (browser.isWeixin) { if (browser.isWeixin) {
this.isweixinPay() this.isweixinPay()
} }
this.judgeIsRedPacket();
// 红包链接进入详情也 this.judgeIsRedPacket();
if (getParam('share_code')) {
this.setState({
isRedPacket: true
});
}
if(getParam('ac') && Number(getParam('ac')) === 11) { // 红包链接进入详情也
this.getBorwerCourse(); if (getParam('share_code')) {
} this.setState({
isRedPacket: true
});
}
if (getParam('ac') && Number(getParam('ac')) === 11) {
this.getBorwerCourse();
} }
getBorwerCourse = () => { }
http.get(`${API.home}/sys/user/blessing`, {type: 4, course_id: getParam('id')}).then(res => {
let {code, data: {today_browsed_courses}} = res.data; getBorwerCourse = () => {
if(code === 200) { http.get(`${API.home}/sys/user/blessing`, {type: 4, course_id: getParam('id')}).then(res => {
let currentCourseId = getParam('id'); let {code, data: {today_browsed_courses}} = res.data;
if(today_browsed_courses.includes(Number(currentCourseId))) { if (code === 200) {
this.setState({ let currentCourseId = getParam('id');
countDownTime: '任务完成' if (today_browsed_courses.includes(Number(currentCourseId))) {
}); this.setState({
}else{ countDownTime: '任务完成'
this.startActivity(); });
} } else {
} this.startActivity();
}
}
})
}
startActivity = () => {
let _this = this;
let countDownInterval = setInterval(function () {
let countDown = parseInt(_this.state.countDownTime);
countDown--;
if (countDown > 0) {
_this.setState({
countDownTime: countDown + 's'
});
} else if (countDown === 0) {
clearInterval(countDownInterval);
countDownInterval = null;
http.post(`${API.home}/sys/add/blessing`, {type: 4, course_id: getParam('id')}).then(res => {
let {code} = res.data;
if (code === 200) {
_this.setState({
countDownTime: '任务完成'
});
}
}) })
} }
}, 1000)
}
// 判断时候未红包课程
judgeIsRedPacket = () => {
http.get(`${API.home}/sys/redPacket/showShareActive/${getParam('id')}`).then(res => {
const {code, data} = res.data;
if (code === 200) {
this.setState({
isRedPacket: data.is_show
});
}
})
}
startActivity = () => { componentDidUpdate(prevProps) {
let _this = this; if (prevProps.user.hasError !== this.props.user.hasError) {
let countDownInterval = setInterval(function() { this.fetchCourseInfo()
let countDown = parseInt(_this.state.countDownTime); }
countDown--; }
if(countDown > 0) {
payCallback = () => {
const _this = this;
if (!getParam('oid')) {
return;
} else {
this.setState({
singMess: JSON.parse(window.localStorage.getItem('singMess'))
})
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus);
_this.intervalPayStatus = null;
// 获取课程类型
http.get(`${API['base-api']}/class_order_status/${getParam('oid')}`).then((res) => {
if (Number(res.data.data.errno) === 200) {
// 正常购买单集成功
_this.setState({ _this.setState({
countDownTime: countDown + 's' singleType: 6,
});
} else if(countDown === 0) {
clearInterval(countDownInterval);
countDownInterval = null;
http.post(`${API.home}/sys/add/blessing`, {type: 4, course_id: getParam('id')}).then(res => {
let {code} = res.data;
if(code === 200) {
_this.setState({
countDownTime: '任务完成'
});
}
}) })
} } else if (Number(res.data.data.errno) === 201) {
}, 1000) // 0元参团
} _this.setState({
singleType: 4,
// 判断时候未红包课程 })
judgeIsRedPacket = () => { } else if (Number(res.data.data.errno) === 202) {
http.get(`${API.home}/sys/redPacket/showShareActive/${getParam('id')}`).then(res => { // 0元购
const {code, data} = res.data; _this.setState({
if (code === 200) { singleType: 3,
this.setState({ })
isRedPacket: data.is_show } else if (Number(res.data.data.errno) === 203) {
}); // 三天内特价
} _this.setState({
nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price,
singleType: 2,
isPdd: res.data.data.data.is_pdd,
})
} else {
Toast.info(res.data.data.msg, 2)
}
})
}
}) })
}, 1000)
} }
};
componentDidUpdate(prevProps) { isweixinPay = () => {
if (prevProps.user.hasError !== this.props.user.hasError) { let _this = this;
this.fetchCourseInfo() let weixin_code = getParam('code');
} if (weixin_code) {
} if (!getParam('oid')) {
return
payCallback = () => { } else {
const _this = this; // this.props.weixinPay(weixin_code)
if (!getParam('oid')) { this.setState({
return; singMess: JSON.parse(window.localStorage.getItem('singMess'))
} else { });
this.setState({ http.get(`${API['base-api']}/pay/wxpay/pub_charge/oid/${getParam('oid')}/code/${weixin_code}`).then((res) => {
singMess: JSON.parse(window.localStorage.getItem('singMess')) if (res.data.errno === 0) {
}) const data = res.data.data;
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => { function onBridgeReady() {
if (res.data.errno === 401) { WeixinJSBridge.invoke(
clearInterval(_this.intervalPayStatus); 'getBrandWCPayRequest', {
_this.intervalPayStatus = null; "appId": data.appId, //公众号名称,由商户传入
// 获取课程类型 "timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数
http.get(`${API['base-api']}/class_order_status/${getParam('oid')}`).then((res) => { "nonceStr": data.nonceStr, //随机串
"package": data.package,
"signType": data.signType, //微信签名方式:
"paySign": data.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
Toast.info('支付成功', 2);
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus);
_this.intervalPayStatus = null;
// 获取课程类型
http.get(`${API['base-api']}/class_order_status/${getParam('oid')}`).then((res) => {
if (Number(res.data.data.errno) === 200) { if (Number(res.data.data.errno) === 200) {
// 正常购买单集成功 // 正常购买单集成功
_this.setState({ _this.setState({
singleType: 6, singleType: 6,
}) })
} else if (Number(res.data.data.errno) === 201) { } else if (Number(res.data.data.errno) === 201) {
// 0元参团 // 0元参团
_this.setState({ _this.setState({
singleType: 4, singleType: 4,
}) })
} else if (Number(res.data.data.errno) === 202) { } else if (Number(res.data.data.errno) === 202) {
// 0元购 // 0元购
_this.setState({ _this.setState({
singleType: 3, singleType: 3,
}) })
} else if (Number(res.data.data.errno) === 203) { } else if (Number(res.data.data.errno) === 203) {
// 三天内特价 // 三天内特价
_this.setState({ _this.setState({
nowPrice: res.data.data.data.now_price, nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price, laterPrice: res.data.data.data.three_day_later_price,
singleType: 2, singleType: 2,
isPdd: res.data.data.data.is_pdd, isPdd: res.data.data.data.is_pdd,
}) })
} else { } else {
Toast.info(res.data.data.msg, 2) Toast.info(res.data.data.msg, 2)
} }
}) })
}
})
}, 1000)
}
};
isweixinPay = () => {
let _this = this;
let weixin_code = getParam('code');
if (weixin_code) {
if (!getParam('oid')) {
return
} else {
// this.props.weixinPay(weixin_code)
this.setState({
singMess: JSON.parse(window.localStorage.getItem('singMess'))
});
http.get(`${API['base-api']}/pay/wxpay/pub_charge/oid/${getParam('oid')}/code/${weixin_code}`).then((res) => {
if (res.data.errno === 0) {
const data = res.data.data;
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": data.appId, //公众号名称,由商户传入
"timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr": data.nonceStr, //随机串
"package": data.package,
"signType": data.signType, //微信签名方式:
"paySign": data.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
Toast.info('支付成功', 2);
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus);
_this.intervalPayStatus = null;
// 获取课程类型
http.get(`${API['base-api']}/class_order_status/${getParam('oid')}`).then((res) => {
if (Number(res.data.data.errno) === 200) {
// 正常购买单集成功
_this.setState({
singleType: 6,
})
} else if (Number(res.data.data.errno) === 201) {
// 0元参团
_this.setState({
singleType: 4,
})
} else if (Number(res.data.data.errno) === 202) {
// 0元购
_this.setState({
singleType: 3,
})
} else if (Number(res.data.data.errno) === 203) {
// 三天内特价
_this.setState({
nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price,
singleType: 2,
isPdd: res.data.data.data.is_pdd,
})
} else {
Toast.info(res.data.data.msg, 2)
}
})
}
})
}, 1000)
} else {
alert('支付失败')
}
}
)
} }
})
}, 1000)
} else {
alert('支付失败')
}
}
)
}
if (typeof WeixinJSBridge == "undefined") { if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) { if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false) document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false)
} else if (document.attachEvent) { } else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady) document.attachEvent('WeixinJSBridgeReady', onBridgeReady)
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady) document.attachEvent('onWeixinJSBridgeReady', onBridgeReady)
} }
} else { } else {
onBridgeReady() onBridgeReady()
}
} else {
Toast.info(res.data.msg, 2)
}
})
} }
} } else {
Toast.info(res.data.msg, 2)
}
})
}
} }
}
// 判断支付是否成功
check = (oid) => { // 判断支付是否成功
check = (oid) => {
this.setState({
singMess: JSON.parse(window.localStorage.getItem('singMess'))
})
http.get(`${API['base-api']}/class_order_status/${oid}`).then((res) => {
if (Number(res.data.data.errno) === 200) {
// 正常购买单集成功
this.setState({ this.setState({
singMess: JSON.parse(window.localStorage.getItem('singMess')) singleType: 6
}) })
http.get(`${API['base-api']}/class_order_status/${oid}`).then((res) => { } else if (Number(res.data.data.errno) === 201) {
if (Number(res.data.data.errno) === 200) { // 0元参团
// 正常购买单集成功 this.setState({
this.setState({ singleType: 4
singleType: 6 })
}) } else if (Number(res.data.data.errno) === 202) {
} else if (Number(res.data.data.errno) === 201) { // 0元购
// 0元参团 this.setState({
this.setState({ singleType: 3
singleType: 4 })
}) } else if (Number(res.data.data.errno) === 203) {
} else if (Number(res.data.data.errno) === 202) { // 三天内特价
// 0元购 this.setState({
this.setState({ nowPrice: res.data.data.data.now_price,
singleType: 3 laterPrice: res.data.data.data.three_day_later_price,
}) singleType: 2,
} else if (Number(res.data.data.errno) === 203) { isPdd: res.data.data.data.is_pdd,
// 三天内特价
this.setState({
nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price,
singleType: 2,
isPdd: res.data.data.data.is_pdd,
})
} else {
Toast.info(res.data.data.msg, 2)
}
}) })
} else {
Toast.info(res.data.data.msg, 2)
}
})
}
payCallBack = (singleType, nowPrice, laterPrice) => {
// Toast.info(singleType, 2);
const _this = this;
if (singleType === 2) {
_this.setState({
singleType,
nowPrice,
laterPrice
})
} else {
_this.setState({
singleType,
})
} }
};
payCallBack = (singleType, nowPrice, laterPrice) => { fetchCourseInfo = () => {
// Toast.info(singleType, 2); const id = getParam('id');
const _this = this; http.get(`${API.home}/m/course/detail/${id}`).then((res) => {
if (singleType === 2) { const {data, code} = res.data;
_this.setState({ if (code === 200) {
singleType, if (data['redirect_url'] !== '') {
nowPrice, window.location.href = data['redirect_url']
laterPrice
})
} else {
_this.setState({
singleType,
})
} }
}; this.setState({
fetchCourseInfo = () => { course: data
const id = getParam('id'); });
http.get(`${API.home}/m/course/detail/${id}`).then((res) => { if (data.course_info) {
const {data, code} = res.data; if (data.course_info.is_it_course == 1) {
if (code === 200) { this.props.history.push(`/python?id=${id}`)
if(data['redirect_url'] !== ''){ }
window.location.href = data['redirect_url']
} let course_info = data.course_info;
document.title = `${course_info.course_title} - 七月在线`;
if (course_info.group_status === 3 || course_info.group_status === 4) {
let endTime = course_info.pdd_group_info.groupon_member.end_time;
if (endTime && endTime > 0) {
let date = endTime * 1000,
hours = 0,
minutes = 0,
seconds = 0;
setInterval(() => {
date -= 1000
hours = `${parseInt(date / (60 * 60 * 1000))}`.padStart(2, 0);
minutes = `${parseInt((date - hours * 3600000) / 60000)}`.padStart(2, 0);
seconds = `${parseInt((date - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
this.setState({ this.setState({
course: data countdown: `${hours}:${minutes}:${seconds}`
}); });
if (data.course_info) { }, 1000)
if(data.course_info.is_it_course == 1){
this.props.history.push(`/python?id=${id}`)
}
let course_info = data.course_info;
document.title = `${course_info.course_title} - 七月在线`;
if (course_info.group_status === 3 || course_info.group_status === 4) {
let endTime = course_info.pdd_group_info.groupon_member.end_time;
if(endTime && endTime > 0) {
let date = endTime * 1000,
hours = 0,
minutes = 0,
seconds = 0;
setInterval(() => {
date -= 1000
hours = `${parseInt(date / (60 * 60 * 1000))}`.padStart(2, 0);
minutes = `${parseInt((date - hours * 3600000) / 60000)}`.padStart(2, 0);
seconds = `${parseInt((date - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
this.setState({
countdown: `${hours}:${minutes}:${seconds}`
});
}, 1000)
}
}
wxShare({
title: course_info.course_title,
desc: course_info.index_description,
link: encodeURI(location.origin + '/detail?id=' + getParam('id')),
imgUrl: course_info.image_name
});
}
} }
}); }
} wxShare({
title: course_info.course_title,
desc: course_info.index_description,
link: encodeURI(location.origin + '/detail?id=' + getParam('id')),
imgUrl: course_info.image_name
});
}
// 点击子组件试听按钮 }
toAudition = (vCourseId,videoId) => { });
const {user} = this.props }
const uid = user && user.data && user.data.uid
if (!uid) { // 点击子组件试听按钮
this.props.history.push('/passport/login') toAudition = (vCourseId, videoId) => {
const {user} = this.props
const uid = user && user.data && user.data.uid
if (!uid) {
this.props.history.push('/passport/login')
} else {
if (videoId == '' || videoId == 0 || videoId == undefined) {
return false;
}
http.post(`${API['base-api']}/sys/get_class_audition?video_id=${videoId}`).then((res) => {
if (res.data.errno == 200) {
this.props.history.push(`/play/video?id=${vCourseId + '&video_id=' + videoId}`)
} else { } else {
if(videoId == '' || videoId == 0 || videoId == undefined){ Toast.info(res.data.msg, 2);
return false;
}
http.post(`${API['base-api']}/sys/get_class_audition?video_id=${videoId}`).then((res) => {
if (res.data.errno == 200) {
this.props.history.push(`/play/video?id=${vCourseId + '&video_id=' + videoId}`)
}else {
Toast.info(res.data.msg, 2);
}
})
// this.setState({
// auditionBox: true,
// })
} }
})
// this.setState({
// auditionBox: true,
// })
} }
// 点击子组件单集购买按钮 }
toSingleset = (item) => { // 点击子组件单集购买按钮
const {user} = this.props toSingleset = (item) => {
const uid = user && user.data && user.data.uid const {user} = this.props
if (!uid) { const uid = user && user.data && user.data.uid
this.props.history.push('/passport/login') if (!uid) {
} else { this.props.history.push('/passport/login')
this.setState({ } else {
singleBox: true, this.setState({
singleType: 1, singleBox: true,
singMess: item singleType: 1,
}); singMess: item
window.localStorage.setItem('singMess', JSON.stringify(item)) });
} window.localStorage.setItem('singMess', JSON.stringify(item))
} }
}
// componentWillReceiveProps(nextProps) { // 加入购物车 type:1 加入购物车,2加入购物车并跳转到购物车页面去支付
// let _this = this; toCart = (type) => {
// if (nextProps.courseInfo.course_info) { const {history, addCourseToCart} = this.props;
// let courseInfo = nextProps.courseInfo.course_info; let data = {
// if (courseInfo.group_status === 3 || courseInfo.group_status === 4) { course_id: getParam('id')
// let endTime = courseInfo.pdd_group_info.groupon_member.end_time;
// let date = endTime * 1000,
// hours = 0,
// minutes = 0,
// seconds = 0;
// setInterval(() => {
// date -= 1000
// hours = `${parseInt(date / (60 * 60 * 1000))}`.padStart(2, 0);
// minutes = `${parseInt((date - hours * 3600000) / 60000)}`.padStart(2, 0);
// seconds = `${parseInt((date - hours * 3600000 - minutes * 60000) / 1000)}`.padStart(2, 0);
// _this.setState({
// countdown: `${hours}:${minutes}:${seconds}`
// });
// }, 1000)
// }
// }
// }
// 加入购物车 type:1 加入购物车,2加入购物车并跳转到购物车页面去支付
toCart = (type) => {
const {history, addCourseToCart} = this.props;
let data = {
course_id: getParam('id')
};
http.post(`${API.home}/m/cart/add`, data).then((res) => {
if (res.data.code === 200) {
if (type === 1) {
Toast.info('已加入购物车', 2)
// this.props.getCourses()
// document.location.reload()
addCourseToCart();
this.fetchCourseInfo();
} else {
history.replace('/shopcart');
}
} else if (res.data.code === 15001) {
history.replace('/shopcart');
} else if (res.data.code === 4030) {
history.replace('/passport');
} else {
Toast.info(res.data.msg, 2);
}
})
}; };
http.post(`${API.home}/m/cart/add`, data).then((res) => {
invitedFriends = () => { if (res.data.code === 200) {
// const {course_title, image_name, course_id, pdd_group_info, pdd_group_info: {groupon_member, groupon_member: {number}, price}} = this.state.course.course_info; if (type === 1) {
// if (browser.isWeixin) { Toast.info('已加入购物车', 2)
// wxShare({ // this.props.getCourses()
// title: `【仅剩${number}个名额】我${price}元拼了《${course_title}》`, // document.location.reload()
// desc: course_title, addCourseToCart();
// link: location.href, this.fetchCourseInfo();
// imgUrl: image_name, } else {
// }); history.replace('/shopcart');
// } else {
// Toast.info('请在微信中使用分享功能!', 2);
// }
const {history} = this.props;
const {course = {}} = this.state;
if (course.course_info && course.course_info.self_oid) {
history.push(`/togroup?id=${course.course_info.self_oid}`);
} }
} else if (res.data.code === 15001) {
history.replace('/shopcart');
} else if (res.data.code === 4030) {
history.replace('/passport');
} else {
Toast.info(res.data.msg, 2);
}
})
};
invitedFriends = () => {
// const {course_title, image_name, course_id, pdd_group_info, pdd_group_info: {groupon_member, groupon_member: {number}, price}} = this.state.course.course_info;
// if (browser.isWeixin) {
// wxShare({
// title: `【仅剩${number}个名额】我${price}元拼了《${course_title}》`,
// desc: course_title,
// link: location.href,
// imgUrl: image_name,
// });
// } else {
// Toast.info('请在微信中使用分享功能!', 2);
// }
const {history} = this.props;
const {course = {}} = this.state;
if (course.course_info && course.course_info.self_oid) {
history.push(`/togroup?id=${course.course_info.self_oid}`);
} }
}
// 自组件传给父组件的boxHide
boxHide = (val) => {
this.setState({
auditionBox: val,
singleBox: val,
singleType: 1
})
this.props.history.push(`/detail?id=${getParam('id')}`);
}
formatTime = seconds => ({
d: Math.floor(seconds / 60 / 60 / 24).toString().padStart(2, '0'),
h: Math.floor(seconds / 60 / 60 % 24).toString().padStart(2, '0'),
m: Math.floor(seconds / 60 % 60).toString().padStart(2, '0')
})
getCourse = (courseId, vCourseId) => {
const {history} = this.props
http.post(`${API.home}/sys/limitFree/receive`, {
course_id: courseId
})
.then(res => {
const {code, msg} = res.data
if (code === 200) {
const instance = Popup({
className: 'get-course-popup',
closable: false,
clickMaskClose: false,
title: <div>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/time_limited_free/M/check.png" alt=""/>
<div>课程有效期7天,快去学习吧~</div>
</div>,
content: <div className={'btns'}>
<button onClick={() => {
instance.close()
this.fetchCourseInfo()
}}>知道了
</button>
<button onClick={() => {
history.push(`/play/video?id=${vCourseId}`)
instance.close()
}}>立即学习
</button>
</div>
})
// 自组件传给父组件的boxHide } else {
boxHide = (val) => { Toast.info(msg, 2, null, false)
this.setState({
auditionBox: val,
singleBox: val,
singleType: 1
})
this.props.history.push(`/detail?id=${getParam('id')}`);
}
render() {
const {course: {course_info = {}}, barInfo, singleBox, singleType, isRedPacket, countDownTime} = this.state;
let courseInfo = '',
service = '',
number = 0,
endTime = 0;
// if (this.props.courseInfo.course_info) {
// courseInfo = this.props.courseInfo.course_info;
// service = courseInfo.service;
if (course_info.group_status === 3 || course_info.group_status === 4) {
number = course_info.pdd_group_info.groupon_member.number;
}
// }
const {share, countdown, list, outList} = this.state;
let href = '';
const {location: {state = {}}} = this.props;
if (state.to && state.to === 'classify') {
href = '/classify'
}
if (state.oid) {
href = '/classify'
}
if (getParam('dist_code')) {
href = '/'
} }
let isCent = course_info.pdd_group_info && course_info.pdd_group_info.price != '0.01'; })
return (
<div>
{
Number(getParam('ac')) === 11 ? (
<div className='activity__blessing'>
<img src='https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/count_donw.png' />
<span className='count__down__time'>{`${countDownTime}`}</span>
</div>
) : (null)
}
<div className='detail-box'>
<HeaderBar
title='课程详情'
arrow={true}
cart={true}
toHref={href}
/>
<ExpandActiveToast/> }
<CallApp className='toapp' path={`/detail/id=${getParam('id')}`} /> render() {
const {course: {course_info = {}}, barInfo, singleBox, singleType, isRedPacket, countDownTime} = this.state;
{/*弹幕*/} const {d, h, m} = this.formatTime(course_info.limit_free_time)
<Barrage isShow={course_info.is_show}/>
{/*课程*/} let courseInfo = '',
<div className='course-content'> service = '',
<div className='cover'> number = 0,
<img src={course_info.image_name} alt=""/> endTime = 0;
{ // if (this.props.courseInfo.course_info) {
course_info.is_aist && // courseInfo = this.props.courseInfo.course_info;
<span className='return_cash'/> // service = courseInfo.service;
} if (course_info.group_status === 3 || course_info.group_status === 4) {
</div> number = course_info.pdd_group_info.groupon_member.number;
<div className="info"> }
<p className='title'>{course_info.course_title}</p> // }
<p className='contact text-overflow-2'>{course_info.simpledescription}</p> const {share, countdown, list, outList} = this.state;
<div className='des'> let href = '';
{ const {location: {state = {}}} = this.props;
course_info.is_baoming === 0 && if (state.to && state.to === 'classify') {
<p className="course-price"> href = '/classify'
<span className="new">¥{course_info.price1}</span> }
<span className="old">¥{course_info.price0}</span> if (state.oid) {
</p> href = '/classify'
} }
{ if (getParam('dist_code')) {
!!course_info.is_deposit && course_info.is_deposit!= 0 && href = '/'
<div className="openExpand"> }
支付定金¥{course_info.deposit_info.deposit_amount},可抵扣¥{course_info.deposit_info.deduction_amount} let isCent = course_info.pdd_group_info && course_info.pdd_group_info.price != '0.01';
</div> return (
} <div>
{
</div> Number(getParam('ac')) === 11 ? (
<div className='activity__blessing'>
<img src='https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/active19_1111/m/count_donw.png'/>
<span className='count__down__time'>{`${countDownTime}`}</span>
</div>
) : (null)
}
<div className='detail-box'>
<HeaderBar
title='课程详情'
arrow={true}
cart={true}
toHref={href}
/>
<ExpandActiveToast/>
<CallApp className='toapp' path={`/detail/id=${getParam('id')}`}/>
{/*弹幕*/}
<Barrage isShow={course_info.is_show}/>
{/*课程*/}
<div className='course-content'>
<div className='cover'>
<img src={course_info.image_name} alt=""/>
{
course_info.is_aist &&
<span className='return_cash'/>
}
</div>
<div className="info">
<p className='title'>{course_info.course_title}</p>
<p className='contact text-overflow-2'>{course_info.simpledescription}</p>
<div className='des'>
{
course_info.is_baoming === 0 && !course_info.is_limit_free &&
<p className="course-price">
<span className="new">¥{course_info.price1}</span>
<span className="old">¥{course_info.price0}</span>
</p>
}
{
!!course_info.is_deposit && course_info.is_deposit != 0 &&
<div className="openExpand">
支付定金¥{course_info.deposit_info.deposit_amount},可抵扣¥{course_info.deposit_info.deduction_amount}
</div>
}
{
course_info.is_limit_free
?
course_info.limit_free_status == 0
? <div className="limit-free">
<span>限时免费</span>
<span className={'origin-price'}>¥{course_info.price0}</span>
</div>
:
course_info.limit_free_status == 1
? <div className={'time-limit'}>
<span>有效期7天,{d}{h}{m}分后过期</span>
</div> </div>
</div> : null
: null
}
</div>
</div>
</div>
{/*正常课程已购买时显示*/} {/*正常课程已购买时显示*/}
{/* {/*
没有权限:不显示 没有权限:不显示
vip及赠课:显示黄的 vip及赠课:显示黄的
不在vip范围内,单独购买:显示蓝的 不在vip范围内,单独购买:显示蓝的
...@@ -589,214 +627,214 @@ class Detail extends Component { ...@@ -589,214 +627,214 @@ class Detail extends Component {
is_pay 1是单独购买 0是买vip赠的 is_pay 1是单独购买 0是买vip赠的
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>
} }
{/*vip课程显示*/}
{
course_info.vip_range && course_info.is_vip == 1 && course_info.is_pay == 0 && course_info.contact_type == 1 && course_info.course_qq &&
<div className="vip">
<p>已开通年会员:{course_info.vip_range}</p>
<p>上课QQ群:{course_info.course_qq},加群请备注您的学号:{course_info.uid}</p>
</div>
}
{
course_info.vip_range && course_info.is_vip == 1 && course_info.is_pay == 0 && course_info.contact_type == 2 && course_info.course_qq &&
<div className="vip">
<p>已开通年会员:{course_info.vip_range}</p>
<p>请添加班主任微信:{course_info.course_qq},添加时备注学号:{course_info.uid}</p>
</div>
}
{/*vip课程显示*/}
{
course_info.vip_range && course_info.is_vip == 1 && course_info.is_pay == 0 && course_info.contact_type == 1 && course_info.course_qq &&
<div className="vip">
<p>已开通年会员:{course_info.vip_range}</p>
<p>上课QQ群:{course_info.course_qq},加群请备注您的学号:{course_info.uid}</p>
</div>
}
{
course_info.vip_range && course_info.is_vip == 1 && course_info.is_pay == 0 && course_info.contact_type == 2 && course_info.course_qq &&
<div className="vip">
<p>已开通年会员:{course_info.vip_range}</p>
<p>请添加班主任微信:{course_info.course_qq},添加时备注学号:{course_info.uid}</p>
</div>
}
{/*定金相关信息*/}
{
!!course_info.is_deposit && course_info.is_deposit!= 0 &&
<Deposit courseInfo={course_info}/>
}
{/*定金相关信息*/}
{
!!course_info.is_deposit && course_info.is_deposit != 0 &&
<Deposit courseInfo={course_info}/>
}
{/*服务承诺*/} {/*服务承诺*/}
<div className='promise'> <div className='promise'>
<label>服务承诺</label> <label>服务承诺</label>
<p> <p>
{ {
course_info.service && course_info.service.length > 0 && course_info.service.map((item, index) => { course_info.service && course_info.service.length > 0 && course_info.service.map((item, index) => {
return ( return (
<span key={index}> {item} </span> <span key={index}> {item} </span>
) )
}) })
} }
</p> </p>
</div> </div>
{/*试听弹窗*/} {/*试听弹窗*/}
<Audition auditionBox={this.state.auditionBox} boxHide={this.boxHide}/> <Audition auditionBox={this.state.auditionBox} boxHide={this.boxHide}/>
{/*单集购买弹窗*/} {/*单集购买弹窗*/}
{ {
singleBox && singleBox &&
<Single <Single
singleType={this.state.singleType} singleType={this.state.singleType}
singleBox={this.state.singleBox} singleBox={this.state.singleBox}
boxHide={this.boxHide} boxHide={this.boxHide}
data={this.state.singMess} data={this.state.singMess}
vcourseId={course_info.v_course_id} vcourseId={course_info.v_course_id}
videoId={this.state.singMess.video_id} videoId={this.state.singMess.video_id}
title={course_info.course_title} title={course_info.course_title}
check={this.check} check={this.check}
courseId={course_info.course_id} courseId={course_info.course_id}
/> />
} }
{/* 单集购买成功弹窗 */} {/* 单集购买成功弹窗 */}
{ {
singleType !== 1 && singleType !== 1 &&
<SingleSuccess <SingleSuccess
boxHide={this.boxHide} boxHide={this.boxHide}
data={this.state.singMess} data={this.state.singMess}
singleType={singleType} singleType={singleType}
vcourseId={course_info.v_course_id} vcourseId={course_info.v_course_id}
videoId={this.state.singMess.video_id} videoId={this.state.singMess.video_id}
nowPrice={this.state.nowPrice} nowPrice={this.state.nowPrice}
isPdd={this.state.isPdd} isPdd={this.state.isPdd}
laterPrice={this.state.laterPrice} laterPrice={this.state.laterPrice}
courseId={course_info.course_id} courseId={course_info.course_id}
/> />
} }
{/*payCallback={this.payCallback}*/} {/*payCallback={this.payCallback}*/}
{/*weixinPay = {this.weixinPay}*/} {/*weixinPay = {this.weixinPay}*/}
{/* 红包 */} {/* 红包 */}
{ {
isRedPacket && isRedPacket &&
<RedPacket <RedPacket
history={this.props.history} history={this.props.history}
country={this.props.country} country={this.props.country}
delCountryNum={this.props.delCountryNum} delCountryNum={this.props.delCountryNum}
userInfo={this.props.user.data} userInfo={this.props.user.data}
/> />
} }
{/*分享赚钱*/} {/*分享赚钱*/}
{ {
course_info.is_dist && course_info.is_dist &&
<ShareRank courseInfo={course_info}/> <ShareRank courseInfo={course_info}/>
} }
{/** {/**
* 拼团 * 拼团
* is_aist: 是否AI特训营 * is_aist: 是否AI特训营
* group_status: 团状态,3:课程有小团 用户没参加小团;4:用户参加了小团 * group_status: 团状态,3:课程有小团 用户没参加小团;4:用户参加了小团
* 拼团价格为1分钱时,不允许参团 * 拼团价格为1分钱时,不允许参团
*/ */
} }
{/*双十一期间不需要显示 不要删除*/} {/*双十一期间不需要显示 不要删除*/}
{ {
isCent && !course_info.is_aist && (course_info.group_status === 3 || course_info.group_status === 4) && isCent && !course_info.is_aist && (course_info.group_status === 3 || course_info.group_status === 4) &&
<Group <Group
courseInfo={course_info} courseInfo={course_info}
history={this.props.history} history={this.props.history}
countdown={countdown} countdown={countdown}
invitedFriends={this.invitedFriends} invitedFriends={this.invitedFriends}
/> />
} }
{/* {/*
* 砍价 * 砍价
* is_baoming 否报名 0-未购买弹出报名 1-已购买弹出开始学习 * is_baoming 否报名 0-未购买弹出报名 1-已购买弹出开始学习
* is_dist 是否分销课程 * is_dist 是否分销课程
* is_bargain 是否砍价课程 * is_bargain 是否砍价课程
*/} */}
{ {
course_info.is_baoming === 0 && (!course_info.is_aist) && course_info.is_bargain && course_info.is_baoming === 0 && (!course_info.is_aist) && course_info.is_bargain &&
<Bargain <Bargain
country={this.props.country} country={this.props.country}
delCountryNum={this.props.delCountryNum} delCountryNum={this.props.delCountryNum}
/> />
} }
{/*课程介绍、大纲*/} {/*课程介绍、大纲*/}
<OutLine <OutLine
data={course_info} data={course_info}
toAudition={this.toAudition} toAudition={this.toAudition}
toSingleset={this.toSingleset} toSingleset={this.toSingleset}
/> />
{/*课程按钮*/} {/*课程按钮*/}
{ {
course_info && course_info &&
<BtnStatus <BtnStatus
country={this.props.country} country={this.props.country}
countdown={countdown} countdown={countdown}
data={course_info} data={course_info}
user={this.props.user} user={this.props.user}
invitedFriends={this.invitedFriends} invitedFriends={this.invitedFriends}
// addCourseToCart={this.props.addCourseToCart} getCourse={this.getCourse}
toCart={this.toCart} // addCourseToCart={this.props.addCourseToCart}
history={this.props.history} toCart={this.toCart}
/> history={this.props.history}
} />
}
{
share ? ( {
<div share ? (
className='groupSuccessMbc' <div
onClick={() => { className='groupSuccessMbc'
this.setState({share: false}) onClick={() => {
}} this.setState({share: false})
> }}
<div className='tipContent'> >
{`还差${number}人,分享到3个群,成团率高达98%`} <div className='tipContent'>
</div> {`还差${number}人,分享到3个群,成团率高达98%`}
<div className='tipArrow'>
<i className='iconfont iconyindao'/>
</div>
</div>
) : null
}
</div> </div>
</div> <div className='tipArrow'>
) <i className='iconfont iconyindao'/>
} </div>
</div>
) : null
}
</div>
</div>
)
}
} }
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
// courseInfo: state.courseInfo, // courseInfo: state.courseInfo,
user: { user: {
...state.user ...state.user
}, },
country: state.country country: state.country
} }
} }
// const mapDispatchToProps = { // const mapDispatchToProps = {
// fetchCoursesListIfNeeded // fetchCoursesListIfNeeded
// } // }
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return bindActionCreators( return bindActionCreators(
{ {
getCourses, getCourses,
addCourseToCart, addCourseToCart,
delCountryNum delCountryNum
}, },
dispatch dispatch
) )
} }
......
...@@ -82,6 +82,22 @@ ...@@ -82,6 +82,22 @@
} }
} }
.limit-free{
span:first-child{
color: #FF2121;
font-size: 15px;
margin-right: 10px;
}
.origin-price{
font-size: 11px;
color: #999;
text-decoration: line-through;
}
}
.time-limit{
color: #FF2121;
}
.isbuy { .isbuy {
display: inline-block; display: inline-block;
width: 66px; width: 66px;
...@@ -253,4 +269,51 @@ ...@@ -253,4 +269,51 @@
bottom: 4px; bottom: 4px;
left: 8px; left: 8px;
} }
}
.get-course-popup {
top: 210px !important;
padding-bottom: 0 !important;
padding-left: 0 !important;
padding-right: 0 !important;
.title {
text-align: center;
margin-bottom: 30px;
img {
width: 30px;
height: 30px;
}
div {
font-size: 14px;
color: #525C65;
}
}
.btns {
border-top: 1px solid #DDD;
display: flex;
height: 40px;
button {
-webkit-appearance: none;
width: 50%;
border: none;
outline: none;
color: #333;
background: #fff;
border-radius: 0 0 5px 5px;
font-size: 15px;
}
& button:first-child {
border-right: 1px solid #DDD;
}
& button:last-child {
color: #09f;
}
}
} }
\ No newline at end of file
import React, { Component } from 'react'
import { http } from "@/utils"
import './index.scss'
import { HeaderBar } from "@common/index"
import { WhiteSpace, Toast } from "antd-mobile";
import VList from '@/common/v-list-base'
import { Popup } from "@common/index"
import WithFullSize from "@/HOCs/WithFullSize"
import { connect } from "react-redux";
import { Link } from "react-router-dom";
function showToast(msg) {
Toast.info(msg, 2, null, false)
}
class LimitFree extends Component {
nav
state = {
tab: {},
courses: [],
navItemStyle: {},
tabActiveIndex: 0
}
componentDidMount() {
this.getData()
}
getData = () => {
Promise.all([http.get(`${API.home}/sys/category`), http.get(`${API.home}/sys/course`)])
.then(res => {
const [tab, courses] = res
const {data: tabData, code: tabCode, msg: tabMsg} = tab.data
const {data: coursesData, code: coursesCode, msg: coursesMsg} = courses.data
if (tabCode == 200) {
this.setState({
tab: tabData
})
} else {
showToast(tabMsg)
}
if (coursesCode === 200) {
this.setState({
courses: coursesData
})
} else {
showToast(coursesMsg)
}
})
}
handleClick = id => {
this.props.history.push(`/detail?id=${id}`)
}
changeTab = (e, index) => {
const {tabActiveIndex} = this.state
if (tabActiveIndex !== index) {
this.setState({
tabActiveIndex: index
}
)
}
}
getCourse = (courseId, vCourseId) => {
const {user, history} = this.props
if (user.hasError) {
history.push('/passport')
return
}
http.post(`${API.home}/sys/limitFree/receive`, {
course_id: courseId
})
.then(res => {
const {code, msg} = res.data
if (code === 200) {
const instance = Popup({
className: 'get-course-popup',
closable: false,
clickMaskClose: false,
title: <div>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/time_limited_free/M/check.png" alt=""/>
<div>课程有效期7天,快去学习吧~</div>
</div>,
content: <div className={'btns'}>
<button onClick={() => {
instance.close()
this.getData()
}}>知道了
</button>
<button onClick={() => {
this.toPlay(vCourseId)
instance.close()
}}>立即学习
</button>
</div>
})
} else {
showToast(msg)
}
})
}
toPlay = id => {
this.props.history.push(`/play/video?id=${id}`)
}
formatTime = seconds => ({
d: Math.floor(seconds / 60 / 60 / 24).toString().padStart(2, '0'),
h: Math.floor(seconds / 60 / 60 % 24).toString().padStart(2, '0'),
m: Math.floor(seconds / 60 % 60).toString().padStart(2, '0')
})
render() {
const {tab, courses, navItemStyle, tabActiveIndex} = this.state
return (
<div className='limit-free'>
<HeaderBar arrow={true} title={'限时免费'}></HeaderBar>
<div className="banner">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/time_limited_free/M/banner.png" alt=""/>
</div>
<nav>
{/*<div className="prev-cover"></div>*/}
<ul ref={el => this.nav = el}>
{
tab && !!tab.length && tab.map((item, index) => {
return (
<li key={index} className={index === tabActiveIndex ? 'active' : ''} style={navItemStyle}
onClick={e => this.changeTab(e, index)}>
<a href={`#category${item.id}`} target={'_self'}>{item.category_name}</a>
</li>
)
})
}
</ul>
<div className="next-cover"></div>
</nav>
<WhiteSpace/>
<div className="course-list">
<ul>
{
tab && !!tab.length && tab.map(category => {
return (
<li key={category.id} className={'category'}>
<h2 id={`category${category.id}`}>
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/time_limited_free/M/category-icon.png"
alt=""/>
<span>{category.category_name}</span>
</h2>
<ul className={'courses'}>
{
courses && courses.length && courses.map((item, index) => {
if (item.category_id != category.id) {
return null
}
/*
* course_status:
* 0未领取 1已领取未过期 2 已领取已过期 3 正常已购买
* */
let des, bottom
switch (item.course_status) {
case 0:
des = <div className={'learner'}>
<i className='iconfont iconRectangleCopy4'/>
<span>{item.play_times}人学习</span>
</div>
bottom = <div className={'bottom'}>
<span className={'red'}>限时免费</span>
<span className={'origin-price'}>¥{item.price0}</span>
<button onClick={e => {
e.stopPropagation()
this.getCourse(item.course_id, item.v_course_id)
}}>免费领取
</button>
</div>
break
case 1:
const {d, h, m} = this.formatTime(item.course_expire)
des = <div className={'remain-time'}>
<i className={'iconfont iconiconfront-21'}/>
<span>{d}{h}{m}分后过期</span>
</div>
bottom = <div className={'bottom'}>
<span className={'purchased'}>已领取</span>
<StudyButton id={item.course_id}/>
</div>
break
case 2:
des = <div className={'remain-time'}>
<i className={'iconfont iconiconfront-21'}/>
<span>{item.play_times}人学习</span>
</div>
bottom = <div className={'bottom'}>
<span className={'red'}>¥{item.price1}</span>
<span className={'origin-price'}>¥{item.price0}</span>
<Link to={`/detail?id=${item.course_id}`}>立即购买</Link>
</div>
break
case 3:
des = <div className={'learner'}>
<i className='iconfont iconRectangleCopy4'/>
<span>{item.play_times}人学习</span>
</div>
bottom = <div className="bottom">
<span className={'purchased'}>已购买</span>
<StudyButton id={item.course_id}/>
</div>
}
const info = (
<div className='info'>
<div className='title'>{item.course_title}</div>
{des}
{bottom}
</div>
)
return (
<VList img={item.image_name}
handleClick={this.handleClick}
id={item.course_id}
info={info}
key={index}
/>
)
})
}
</ul>
</li>
)
})
}
</ul>
</div>
<div className="no-more">
-没有更多了-
</div>
</div>
);
}
}
function StudyButton({id}) {
return <Link to={`/play/video?id=${id}`}>立即学习</Link>
}
export default connect(
state => ({user: state.user}),
null
)
(WithFullSize(LimitFree))
\ No newline at end of file
.limit-free {
background: #F9F9FB;
min-height: 100%;
.banner {
font-size: 0;
img {
width: 100%;
}
}
nav {
position: sticky;
top: 0;
left: 0;
display: flex;
align-items: center;
height: 39px;
background: #fff;
overflow: hidden;
z-index: 999;
.prev-cover, .next-cover {
position: absolute;
top: 0;
width: 44px;
height: 39px;
pointer-events: none;
}
.prev-cover {
left: 0;
background: linear-gradient(90deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
}
.next-cover {
right: 0;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
}
ul {
width: 100%;
height: 100%;
padding: 0 18px;
display: flex;
align-items: center;
overflow-x: auto;
&::-webkit-scrollbar {
display: none;
}
& li:nth-last-child(1) {
margin-right: 0;
}
}
li {
text-align: center;
height: 100%;
line-height: 39px;
flex-shrink: 0;
margin-right: 23px;
&.active {
color: #09f;
border-bottom: 1px solid #09f;
}
}
}
.course-list {
border-top: 1px solid transparent;
}
.category {
padding: 0 12px;
background: #fff;
margin-bottom: 8px;
border-top: 1px solid transparent;
}
h2 {
padding-top: 50px;
margin-top: -50px;
background-clip: content-box;
}
.courses li:nth-last-child(1) {
margin-bottom: 0;
& div {
border-bottom: none;
}
}
.v-list-base-item {
padding: 0;
margin-bottom: 18px;
}
h2 {
display: flex;
align-items: center;
margin: -32px 0 18px;
img {
width: 12px;
height: 12px;
margin-right: 6px;
}
span {
font-size: 16px;
color: #333;
}
}
.iconfont {
font-size: 12px;
margin-right: 4px;
}
.info {
width: 50%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
flex-direction: column;
flex: auto;
font-size: 12px;
color: #999;
.title {
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
font-family: "NotoSansHans-Medium", "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
}
.learner, .remain-time, {
margin-top: -30px;
}
.red {
color: #FF2121;
font-size: 15px;
margin-right: 10px;
}
.origin-price {
color: #999;
font-size: 12px;
text-decoration: line-through;
}
button, a {
width: 68px;
height: 24px;
float: right;
border-radius: 3px;
background: #09f;
border: none;
font-size: 13px;
color: #fff;
line-height: 24px;
text-align: center;
}
button {
-webkit-appearance: none;
outline: 0;
}
.bottom {
width: 100%;
height: 24px;
align-self: flex-end;
font-size: 0;
line-height: 24px;
span {
font-size: 12px;
}
.purchased {
color: #09f;
}
}
}
.no-more {
width: 375px;
height: 82px;
line-height: 82px;
background: #F7F9FC;
font-size: 14px;
color: #AAA;
text-align: center;
}
}
.get-course-popup {
top: 210px !important;
padding-bottom: 0 !important;
padding-left: 0 !important;
padding-right: 0 !important;
.title {
text-align: center;
margin-bottom: 30px;
img {
width: 30px;
height: 30px;
}
div {
font-size: 14px;
color: #525C65;
}
}
.btns {
border-top: 1px solid #DDD;
display: flex;
height: 40px;
button {
-webkit-appearance: none;
width: 50%;
border: none;
outline: none;
color: #333;
background: #fff;
border-radius: 0 0 5px 5px;
font-size: 15px;
}
& button:first-child {
border-right: 1px solid #DDD;
}
& button:last-child {
color: #09f;
}
}
}
\ No newline at end of file
import React, {Component} from 'react'; import React, { Component } from 'react';
import './index.scss'; import './index.scss';
import {HeaderBar, VList} from '../../common' import { HeaderBar, VList } from '../../common'
import { http } from "@/utils"; import { http, dateCountDown } from "@/utils";
import {Link} from 'react-router-dom' import { Link } from 'react-router-dom'
import {Toast} from 'antd-mobile' import { Toast } from 'antd-mobile'
import {connect} from "react-redux" import { connect } from "react-redux"
import {getCourses} from './../detail/actions';
import Loading from '@/common/Loading' import Loading from '@/common/Loading'
class Purchased extends Component { class Purchased extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
data: [], data: [],
isLoading: true isLoading: true
}
} }
}
componentDidMount() { componentDidMount() {
this.getList() this.getList()
} }
// 获取订单 // 获取订单
getList = () => { getList = () => {
http.get(`${API.home}/m/my/courses`,).then((res) => { http.get(`${API.home}/m/my/courses`,).then((res) => {
if (res.data.code === 200) { if (res.data.code === 200) {
this.setState({ this.setState({
data: res.data.data, data: res.data.data,
isLoading: false isLoading: false
})
} else {
Toast.info(res.data.msg, 2);
}
}) })
} } else {
Toast.info(res.data.msg, 2);
toCourseDetail = (id) => { }
const { dispatch, history } = this.props; })
// dispatch(getCourses(id, () => { }
history.push(`/detail?id=${id}`)
// }));
}
render() { toCourseDetail = (id) => {
const {user} = this.props const {dispatch, history} = this.props;
const uid = user && user.data && user.data.uid // dispatch(getCourses(id, () => {
return ( history.push(`/detail?id=${id}`)
<div className='purchased-box'> // }));
<HeaderBar arrow={true} title='已购课程' cart={false} toHref='/my' /> }
<Loading isLoading={this.state.isLoading}> render() {
{ const {user} = this.props
this.state.data && this.state.data.length > 0 ? const uid = user && user.data && user.data.uid
<div className="purchased-body"> return (
<div className='tip'>加群请备注您的学号:{uid}</div> <div className='purchased-box'>
{ <HeaderBar arrow={true} title='已购课程' cart={false} toHref='/my'/>
this.state.data.map((item, index) => { <Loading isLoading={this.state.isLoading}>
const Info = ( {
<div className="info"> this.state.data && this.state.data.length > 0 ?
<p className='title' onClick={() => this.toCourseDetail(item.course_id)}> <div className="purchased-body">
{/* <Link to={`/detail?id=${item.course_id}`}> */} <div className='tip'>加群请备注您的学号:{uid}</div>
{item.course_title} {
{/* </Link> */} this.state.data.map((item, index) => {
</p> const Info = (
<p className='contact text-overflow-2'>{item.simpledescription}</p> <div className="info">
<p className='title' onClick={() => this.toCourseDetail(item.course_id)}>
{item.course_title}
</p>
<p className='contact text-overflow-2'>{item.simpledescription}</p>
{ {
item.is_aist && item.is_aist &&
<div className='des'>助教微信:{item.assist_weixin}</div> <div className='des'>助教微信:{item.assist_weixin}</div>
} }
{ {
!item.is_aist && item.contact_type == 1 && item.course_qq && !item.is_aist && item.contact_type == 1 && item.course_qq &&
<div className='des'>QQ群:{item.course_qq}</div> <div className='des'>QQ群:{item.course_qq}</div>
} }
{ {
!item.is_aist && item.contact_type == 2 && item.course_qq && !item.is_aist && item.contact_type == 2 && item.course_qq &&
<div className='des'>班主任微信:{item.course_qq}</div> <div className='des'>班主任微信:{item.course_qq}</div>
} }
</div> </div>
) )
const status = ( const status = (
item.is_aist && <span className='status'>返现</span> item.is_aist && <span className='status'>返现</span>
) )
const courseExpire = ( const courseExpire = (
item.course_expire && item.course_expire!='' && item.course_expire && item.course_expire != '' &&
<span className='course-expire'>{item.course_expire}</span> <span className='course-expire'>{item.course_expire}</span>
) )
return ( return (
<VList <VList
key={index} key={index}
img={item.image_name} img={item.image_name}
id={item.course_id} id={item.course_id}
info={Info} info={Info}
status={status} status={status}
courseExpire={courseExpire} courseExpire={courseExpire}
toDetail={this.toCourseDetail} toDetail={this.toCourseDetail}
/> />
) )
}) })
} }
</div> </div>
: <div className="cart-tip"> : <div className="cart-tip">
<p className='cart-mess'>您还没有课程哦,快去逛逛吧~</p> <p className='cart-mess'>您还没有课程哦,快去逛逛吧~</p>
<Link to='/classify'>去逛逛</Link> <Link to='/classify'>去逛逛</Link>
</div> </div>
} }
</Loading> </Loading>
</div> </div>
) )
} }
} }
export default connect( export default connect(
state => ({user: state.user}), state => ({user: state.user}),
null null
)(Purchased) )(Purchased)
html, body, #root { html, body, #root {
height: 100%!important; height: 100% !important;
} }
.purchased-box {
width: 100%;
height: 100%;
//background-color: $bg_f5f5f5;
.purchased-box {
width: 100%;
height: 100%;
//background-color: $bg_f5f5f5;
.tip {
width: 100%;
height: 30px;
line-height: 30px;
font-size: 12px;
color: $color_333;
text-align: center;
background-color: $bg_FFF4CE;
margin-bottom: 10px;
}
.purchased-body { .tip {
background-color: $bg_fff; width: 100%;
height: 30px;
line-height: 30px;
font-size: 12px;
color: $color_333;
text-align: center;
background-color: $bg_FFF4CE;
margin-bottom: 10px;
}
.purchased-body {
background-color: $bg_fff;
}
.v-list-item {
background-color: #fff;
.content {
padding-bottom: 10px;
border-bottom: 1px solid #e7eaf1;
.cover {
flex: inherit;
width: 42.2%;
img {
width: 100%;
}
}
} }
.v-list-item { .info {
background-color: #fff; width: 52.3%;
position: relative;
.content { display: block;
padding-bottom: 10px;
border-bottom: 1px solid #e7eaf1;
.cover {
flex: inherit;
width: 42.2%;
img { .title {
width: 100%; font-size: 16px;
} color: $color_333;
} overflow: hidden;
} text-overflow: ellipsis;
white-space: nowrap;
height: 16px;
line-height: 16px;
}
.contact {
font-size: 14px;
color: $color_666;
margin-top: 14px;
}
.info { .des {
width: 52.3%; position: absolute;
position: relative; bottom: 5px;
display: block; color: $active;
font-size: 14px;
.title { height: 14px;
font-size: 16px; line-height: 14px;
color: $color_333; }
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
height: 16px;
line-height: 16px;
}
.contact {
font-size: 14px;
color: $color_666;
margin-top: 14px;
}
.des {
position: absolute;
bottom: 5px;
color: $active;
font-size: 14px;
height: 14px;
line-height: 14px;
}
}
} }
}
.cart-tip { .cart-tip {
color: #555; color: #555;
margin-top: 140px; margin-top: 140px;
text-align: center; text-align: center;
.iconfridge {
font-size: 21px;
}
.cart-mess {
font-size: 12px;
color: $color_666;
}
a { .iconfridge {
display: inline-block; font-size: 21px;
width: 130px;
height: 30px;
border: 1px solid $bg_active;
border-radius: 15px;
font-size: 16px;
margin-top: 30px;
color: $active;
text-align: center;
line-height: 28px;
}
} }
.status { .cart-mess {
position: absolute; font-size: 12px;
top: 0; color: $color_666;
right: 0;
padding: 2px 6px;
border-radius: 11px 0 0 11px;
font-size: 14px;
color: #fff;
background: linear-gradient(to bottom, #FF4000, #FD7700);
} }
.course-expire{
display: inline-block; a {
text-align: center; display: inline-block;
position: absolute; width: 130px;
bottom: 10px; height: 30px;
left: 0; border: 1px solid $bg_active;
width:92px; border-radius: 15px;
height:20px; font-size: 16px;
line-height: 21px; margin-top: 30px;
background-color: #FF3A3A; color: $active;
border-radius:0 10px 10px 0; text-align: center;
color: #fff; line-height: 28px;
font-size: 12px;
} }
}
.status {
position: absolute;
top: 0;
right: 0;
padding: 2px 6px;
border-radius: 11px 0 0 11px;
font-size: 14px;
color: #fff;
background: linear-gradient(to bottom, #FF4000, #FD7700);
}
.course-expire {
display: inline-block;
text-align: center;
position: absolute;
bottom: 10px;
left: 0;
width: 92px;
height: 20px;
line-height: 21px;
background-color: #FF3A3A;
border-radius: 0 10px 10px 0;
color: #fff;
font-size: 12px;
}
} }
\ No newline at end of file
...@@ -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_restricted && item.is_aist &&
<div className='contact'>助教微信:{item.assist_weixin}</div>
}
{
!item.is_restricted && !item.is_aist && item.contact_type == 1 && item.course_qq &&
<div className='contact'>QQ群:{item.course_qq}</div>
}
{
!item.is_restricted && !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, Link } 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'
...@@ -21,862 +21,958 @@ import './CustomPlayButton' ...@@ -21,862 +21,958 @@ import './CustomPlayButton'
let alert = Modal.alert let alert = Modal.alert
function ProgressShareModal(props) { function ProgressShareModal(props) {
return ( return (
props.isShow && props.isShow &&
<div className='progress-share-modal-wrapper'> <div className='progress-share-modal-wrapper'>
<div className="progress-share-modal"> <div className="progress-share-modal">
<div className="title">每日打卡</div> <div className="title">每日打卡</div>
<ul className="progress-container"> <ul className="progress-container">
<li> <li>
<div className="title">累计学习</div> <div className="title">累计学习</div>
<div className="number"><span className='num'>{props.data.learn_day_count}</span>天</div> <div className="number"><span className='num'>{props.data.learn_day_count}</span>天</div>
</li> </li>
<li> <li>
<div className="title">行动力超过</div> <div className="title">行动力超过</div>
<div className="number"><span className='num'>{parseFloat(props.data.action_power)}</span>% <div className="number"><span className='num'>{parseFloat(props.data.action_power)}</span>%
</div>
</li>
</ul>
<div className="share-container">
<div className="title">分享到</div>
<ul>
<li className='share-icon'>
<a style={{display: 'block'}} href={props.data.url}>
<div className="icon"><i className='iconfont iconweixinzhifu'/></div>
<div className='text'>微信好友</div>
</a>
</li>
<li className='share-icon'>
<a style={{display: 'block'}} href={props.data.url}>
<div className="icon"><i className='iconfont iconpengyouquaniconx'/></div>
<div className='text'>朋友圈</div>
</a>
</li>
</ul>
</div>
<i className="iconfont iconiconfront-2 close" onClick={props.closeShareModal}/>
</div> </div>
</li>
</ul>
<div className="share-container">
<div className="title">分享到</div>
<ul>
<li className='share-icon'>
<a style={{display: 'block'}} href={props.data.url}>
<div className="icon"><i className='iconfont iconweixinzhifu'/></div>
<div className='text'>微信好友</div>
</a>
</li>
<li className='share-icon'>
<a style={{display: 'block'}} href={props.data.url}>
<div className="icon"><i className='iconfont iconpengyouquaniconx'/></div>
<div className='text'>朋友圈</div>
</a>
</li>
</ul>
</div> </div>
) <i className="iconfont iconiconfront-2 close" onClick={props.closeShareModal}/>
</div>
</div>
)
} }
class Video extends Component { class Video extends Component {
video //video element video //video element
player //video player instance player //video player instance
courseID courseID
ws //websocket instance ws //websocket instance
timer timer
token token
count count
watchSec watchSec
previousPlaybackRate = 1 previousPlaybackRate = 1
currentPlaybackRate = 1 currentPlaybackRate = 1
reconnect = true reconnect = true
// timeEnough = false // timeEnough = false
recordSocket recordSocket
recordTimer recordTimer
isCurrentVideoFirstPlay = true isCurrentVideoFirstPlay = true
RECENTLEARN = "recent_learn" RECENTLEARN = "recent_learn"
state = { state = {
title: '', title: '',
courseId: null, courseId: null,
videoList: [], videoList: [],
datum: [], datum: [],
currentVideoSrc: '', currentVideoSrc: '',
activeIndex: 0, activeIndex: 0,
isAuth: true, isAuth: true,
course: {}, // course.course_id 为 0 或 '' 时 为免费课程 course: {}, // course.course_id 为 0 或 '' 时 为免费课程
salePrice: null, salePrice: null,
vCourseId: null, vCourseId: null,
isLoading: true, isLoading: true,
isShowShareModal: false, isShowShareModal: false,
shareData: {}, shareData: {},
singleBox: false, singleBox: false,
singMess: '', singMess: '',
singleType: 1,// 单集购买需要 singleType: 1,// 单集购买需要
nowPrice: 0,// 单集购买需要 nowPrice: 0,// 单集购买需要
laterPrice: 0,// 单集购买需要 laterPrice: 0,// 单集购买需要
limitFreeNoPromptChecked: false,//是否勾选"不再显示此弹框"选项
showLimitFreePopup: false,
limitFreePopup: {},
isShowNeverShowPopupOption: false, //限时免费课程 播放结束后是否显示"不再显示此弹框"选项
limitFreePopupVideos: JSON.parse(localStorage.getItem('limit-free-popup-videos'))
}
componentDidMount() {
if (window.location.protocol === 'https:') {
window.location.replace('http' + window.location.href.slice(5))
return
} }
this.courseID = getParam('id')
componentDidMount() { if (!this.courseID) {
if (window.location.protocol === 'https:') { this.props.history.replace('/')
window.location.replace('http' + window.location.href.slice(5)) return
return
}
this.courseID = getParam('id')
if (!this.courseID) {
this.props.history.replace('/')
return
}
this.setState({
courseId: this.courseID
})
const {location, location: {state = {}}} = this.props;
if (state.oid) {
this.check(state.oid);
}
if (getParam('is_class') === 1 || getParam('weixinpay')) {
this.payCallback()
}
if (browser.isWeixin) {
this.isweixinPay()
}
this.token = jsCookie.get('token')
this.getVideoList()
this.getDatumCatalog()
} }
this.setState({
// 直接购买 courseId: this.courseID
tobuy = () => { })
// 详情页单集购买到该页面,url中的id不是课程id const {location, location: {state = {}}} = this.props;
const {course = {}} = this.state; if (state.oid) {
http.get(`${API['base-api']}/m/cart/addtopreorder/[${course.course_id}]`).then((res) => { this.check(state.oid);
if (res.data.errno === 0) {
this.props.history.push(`/order?id=${course.course_id}`, {simple: 1})
} else {
Toast.info(res.data.msg, 2);
}
})
} }
// 购买单集 if (getParam('is_class') === 1 || getParam('weixinpay')) {
toSingleset = (item) => { this.payCallback()
// console.log(item);
this.setState({
singleBox: true,
singleType: 1,
singMess: item
})
window.localStorage.setItem('singMess', JSON.stringify(item))
} }
if (browser.isWeixin) {
// 自组件传给父组件的boxHide this.isweixinPay()
boxHide = (val) => {
this.setState({singleBox: val, singleType: 1})
} }
this.token = jsCookie.get('token')
// 单集购买 H5支付成功后回调 this.getVideoList()
payCallback = () => { this.getDatumCatalog()
const _this = this; }
if (!getParam('oid')) {
return; // 直接购买
} else { tobuy = () => {
this.setState({ // 详情页单集购买到该页面,url中的id不是课程id
singMess: JSON.parse(window.localStorage.getItem('singMess')) const {course = {}} = this.state;
}) http.get(`${API['base-api']}/m/cart/addtopreorder/[${course.course_id}]`).then((res) => {
_this.intervalPayStatus = setInterval(function () { if (res.data.errno === 0) {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => { this.props.history.push(`/order?id=${course.course_id}`, {simple: 1})
if (res.data.errno === 401) { } else {
clearInterval(_this.intervalPayStatus); Toast.info(res.data.msg, 2);
_this.intervalPayStatus = null; }
// 获取课程类型 })
http.get(`${API['base-api']}/class_order_status/${getParam('oid')}`).then((res) => { }
if (Number(res.data.data.errno) === 200) { // 购买单集
// 正常购买单集成功 toSingleset = (item) => {
_this.setState({ this.setState({
singleType: 6, singleBox: true,
}) singleType: 1,
} else if (Number(res.data.data.errno) === 201) { singMess: item
// 0元参团 })
_this.setState({ window.localStorage.setItem('singMess', JSON.stringify(item))
singleType: 4, }
})
} else if (Number(res.data.data.errno) === 202) { // 自组件传给父组件的boxHide
// 0元购 boxHide = (val) => {
_this.setState({ this.setState({singleBox: val, singleType: 1})
singleType: 3, }
})
} else if (Number(res.data.data.errno) === 203) { // 单集购买 H5支付成功后回调
// 三天内特价 payCallback = () => {
_this.setState({ const _this = this;
nowPrice: res.data.data.data.now_price, if (!getParam('oid')) {
laterPrice: res.data.data.data.three_day_later_price, return;
singleType: 2, } else {
}) this.setState({
} else { singMess: JSON.parse(window.localStorage.getItem('singMess'))
Toast.info(res.data.data.msg, 2) })
} _this.intervalPayStatus = setInterval(function () {
}) http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
} if (res.data.errno === 401) {
}) clearInterval(_this.intervalPayStatus);
}, 1000) _this.intervalPayStatus = null;
} // 获取课程类型
}; http.get(`${API['base-api']}/class_order_status/${getParam('oid')}`).then((res) => {
// 单集购买 微信内支付成功后回调 if (Number(res.data.data.errno) === 200) {
isweixinPay = () => {
let _this = this;
let weixin_code = getParam('code');
if (weixin_code) {
if (!getParam('oid')) {
return
} else {
this.setState({
singMess: JSON.parse(window.localStorage.getItem('singMess'))
})
// this.props.weixinPay(weixin_code)
http.get(`${API['base-api']}/pay/wxpay/pub_charge/oid/${getParam('oid')}/code/${weixin_code}`).then((res) => {
if (res.data.errno === 0) {
const data = res.data.data;
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": data.appId, //公众号名称,由商户传入
"timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr": data.nonceStr, //随机串
"package": data.package,
"signType": data.signType, //微信签名方式:
"paySign": data.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
Toast.info('支付成功', 2);
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus);
_this.intervalPayStatus = null;
// 获取课程类型
http.get(`${API['base-api']}/class_order_status/${getParam('oid')}`).then((res) => {
if (Number(res.data.data.errno) === 200) {
// 正常购买单集成功
_this.setState({
singleType: 6,
})
} else if (Number(res.data.data.errno) === 201) {
// 0元参团
_this.setState({
singleType: 4,
})
} else if (Number(res.data.data.errno) === 202) {
// 0元购
_this.setState({
singleType: 3,
})
} else if (Number(res.data.data.errno) === 203) {
// 三天内特价
_this.setState({
nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price,
singleType: 2,
})
} else {
Toast.info(res.data.data.msg, 2)
}
})
}
})
}, 1000)
} else {
alert('支付失败')
}
}
)
}
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false)
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady)
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady)
}
} else {
onBridgeReady()
}
} else {
Toast.info(res.data.msg, 2)
}
})
}
}
};
// 判断支付是否成功
check = (oid) => {
this.setState({
singMess: JSON.parse(window.localStorage.getItem('singMess'))
})
http.get(`${API['base-api']}/class_order_status/${oid}`).then((res) => {
if (Number(res.data.data.errno) === 200) {
// 正常购买单集成功 // 正常购买单集成功
this.setState({ _this.setState({
singleType: 6, singleType: 6,
}) })
} else if (Number(res.data.data.errno) === 201) { } else if (Number(res.data.data.errno) === 201) {
// 0元参团 // 0元参团
this.setState({ _this.setState({
singleType: 4, singleType: 4,
}) })
} else if (Number(res.data.data.errno) === 202) { } else if (Number(res.data.data.errno) === 202) {
// 0元购 // 0元购
this.setState({ _this.setState({
singleType: 3, singleType: 3,
}) })
} else if (Number(res.data.data.errno) === 203) { } else if (Number(res.data.data.errno) === 203) {
// 三天内特价 // 三天内特价
this.setState({ _this.setState({
nowPrice: res.data.data.data.now_price, nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price, laterPrice: res.data.data.data.three_day_later_price,
singleType: 2, singleType: 2,
}) })
} else { } else {
Toast.info(res.data.data.msg, 2) Toast.info(res.data.data.msg, 2)
} }
})
}
}) })
}, 1000)
} }
};
// 9502 初始化 监听事件 // 单集购买 微信内支付成功后回调
setupWS = () => { isweixinPay = () => {
this.ws = new WebSocket(API["process-api"]); let _this = this;
this.ws.addEventListener('error', () => { let weixin_code = getParam('code');
this.ws = null if (weixin_code) {
}) if (!getParam('oid')) {
this.ws.addEventListener('close', () => { return
if (this.reconnect) { } else {
this.ws = null this.setState({
setTimeout(() => { singMess: JSON.parse(window.localStorage.getItem('singMess'))
this.setupWS();
}, 1000)
}
clearInterval(this.timer)
this.timer = null;
}) })
this.ws.addEventListener('message', e => { // this.props.weixinPay(weixin_code)
const data = JSON.parse(e.data); http.get(`${API['base-api']}/pay/wxpay/pub_charge/oid/${getParam('oid')}/code/${weixin_code}`).then((res) => {
data.code == 4040 && (this.reconnect = false); if (res.data.errno === 0) {
if(data.code === 0) { const data = res.data.data;
console.log("上次的学习记录" + JSON.stringify(data));
if(data.data && data.data.position) { function onBridgeReady() {
this.player.currentTime(data.data.position); WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": data.appId, //公众号名称,由商户传入
"timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr": data.nonceStr, //随机串
"package": data.package,
"signType": data.signType, //微信签名方式:
"paySign": data.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
Toast.info('支付成功', 2);
_this.intervalPayStatus = setInterval(function () {
http.get(`${API['base-api']}/m/orderState/oid/${getParam('oid')}`).then(res => {
if (res.data.errno === 401) {
clearInterval(_this.intervalPayStatus);
_this.intervalPayStatus = null;
// 获取课程类型
http.get(`${API['base-api']}/class_order_status/${getParam('oid')}`).then((res) => {
if (Number(res.data.data.errno) === 200) {
// 正常购买单集成功
_this.setState({
singleType: 6,
})
} else if (Number(res.data.data.errno) === 201) {
// 0元参团
_this.setState({
singleType: 4,
})
} else if (Number(res.data.data.errno) === 202) {
// 0元购
_this.setState({
singleType: 3,
})
} else if (Number(res.data.data.errno) === 203) {
// 三天内特价
_this.setState({
nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price,
singleType: 2,
})
} else {
Toast.info(res.data.data.msg, 2)
}
})
}
})
}, 1000)
} else {
alert('支付失败')
}
} }
)
} }
})
}
sendMessage = message => { if (typeof WeixinJSBridge == "undefined") {
let readyState = this.ws.readyState, _this = this; if (document.addEventListener) {
if(readyState === 1) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false)
this.ws && this.ws.send(JSON.stringify(message)) } else if (document.attachEvent) {
}else if(readyState === 3) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady)
this.ws.close(); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady)
this.ws = null; }
let reconnect = setTimeout(function() { } else {
clearTimeout(reconnect); onBridgeReady()
reconnect = null; }
_this.ws = new WebSocket(PROCESS_URL); } else {
}, 500); Toast.info(res.data.msg, 2)
} }
})
}
} }
};
// 判断支付是否成功
check = (oid) => {
this.setState({
singMess: JSON.parse(window.localStorage.getItem('singMess'))
})
http.get(`${API['base-api']}/class_order_status/${oid}`).then((res) => {
if (Number(res.data.data.errno) === 200) {
// 正常购买单集成功
this.setState({
singleType: 6,
//视频结束请求接口 })
getShareProgressInfo = () => { } else if (Number(res.data.data.errno) === 201) {
http.get(`${API['base-api']}/m/aist/share_data/${this.courseID}/${this.state.videoList[this.state.activeIndex]['id']}`) // 0元参团
.then(res => { this.setState({
const {data} = res singleType: 4,
if (data.errno == 200) {
this.setState({shareData: data.data, isShowShareModal: true})
}
})
}
//告诉服务端计算进度
countSchedule = () => {
const {videoList, activeIndex, vCourseId, course = {}} = this.state
if (Number(course.course_id) === 0 || course.course_id === '') {
console.log('免费课程 拦截');
return;
}
let ctype = 0;
if (course.is_aist) {
ctype = 2;
}
// 计算进度 根据ctype判断 课程类型 0-视频 1-直播 2-AI特训营
this.sendMessage({
mtype: 'count_schedule',
uid: this.props.user.data.uid,
token: this.token,
platform: 5,
video_id: videoList[activeIndex]['id'],
course_id: this.state.courseId,
v_course_id: vCourseId,
ctype: ctype,
}) })
} else if (Number(res.data.data.errno) === 202) {
// 0元购
this.setState({
singleType: 3,
}
// 发送时间消息
sendWatchTime = (sec, rate) => {
const {videoList, activeIndex, vCourseId, course = {}} = this.state
// 免费课程不发送
// if (Number(course.course_id) === 0 || course.course_id === '') {
// console.log('免费课程 拦截');
// return;
// }
// 时间为0 不发送消息
if (Number(sec) === 0) {
return;
}
let ctype = 0;
if (course.is_aist) {
ctype = 2;
}
// 时间足够不发送
// if(this.timeEnough) {
// console.log('5001 时间足够');
// return;
// }
this.sendMessage({
mtype: 'watch_time',
rate,
time: sec,
video_id: videoList[activeIndex]['id'],
course_id: this.state.courseId,
v_course_id: vCourseId,
uid: this.props.user.data.uid,
token: this.token,
platform: 5,
position: parseInt(this.player.currentTime()),
ctype: ctype,
}) })
} } else if (Number(res.data.data.errno) === 203) {
// 三天内特价
this.setState({
nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price,
singleType: 2,
setupTimer = () => { })
this.count = 0 } else {
this.watchSec = 0 Toast.info(res.data.data.msg, 2)
clearInterval(this.timer) }
this.timer = null; })
this.timer = setInterval(() => { }
if (this.player && this.player.player()) {
if (this.count === 5) { // 9502 初始化 监听事件
this.sendWatchTime(this.watchSec, this.currentPlaybackRate) setupWS = () => {
this.count = this.watchSec = 0 this.ws = new WebSocket(API["process-api"]);
} else { this.ws.addEventListener('error', () => {
!this.player.paused() && this.watchSec++ this.ws = null
!this.player.paused() && this.count++ })
} this.ws.addEventListener('close', () => {
} if (this.reconnect) {
this.ws = null
setTimeout(() => {
this.setupWS();
}, 1000) }, 1000)
}
clearInterval(this.timer)
this.timer = null;
})
this.ws.addEventListener('message', e => {
const data = JSON.parse(e.data);
data.code == 4040 && (this.reconnect = false);
if (data.code === 0) {
if (data.data && data.data.position) {
this.player.currentTime(data.data.position);
}
}
})
}
sendMessage = message => {
let readyState = this.ws.readyState, _this = this;
if (readyState === 1) {
this.ws && this.ws.send(JSON.stringify(message))
} else if (readyState === 3) {
this.ws.close();
this.ws = null;
let reconnect = setTimeout(function () {
clearTimeout(reconnect);
reconnect = null;
_this.ws = new WebSocket(PROCESS_URL);
}, 500);
} }
}
// 初始化视频播放器
initializePlayer = () => { //视频结束请求接口
window.HELP_IMPROVE_VIDEOJS = false; getShareProgressInfo = () => {
this.player = videojs(this.video, { http.get(`${API['base-api']}/m/aist/share_data/${this.courseID}/${this.state.videoList[this.state.activeIndex]['id']}`)
controls: true, .then(res => {
preload: 'auto', const {data} = res
bigPlayButton: false, if (data.errno == 200) {
textTrackDisplay: false, this.setState({shareData: data.data, isShowShareModal: true})
posterImage: false, }
errorDisplay: false, })
playbackRates: ['0.75', '1', '1.5', '2'], }
controlBar: {
pictureInPictureToggle: false //告诉服务端计算进度
} countSchedule = () => {
}) const {videoList, activeIndex, vCourseId, course = {}} = this.state
this.player.addChild('CustomPlayButtonCover') if (Number(course.course_id) === 0 || course.course_id === '') {
this.player.on('play', () => { return;
const {videoList, activeIndex, vCourseId, course = {}} = this.state
// 当视频播放时 看是否是第一次播放(初次进入页面 刷新页面 切换视频 都是第一次播放 需要获取上次的播放时间)
if(this.isCurrentVideoFirstPlay) {
// 当某些原因导致视频暂停时(用户暂停 网络不好等) 再播放时不需要发送
this.isCurrentVideoFirstPlay = false;
// 发送消息 recent_learn
this.ws.send(JSON.stringify({
mtype: this.RECENTLEARN,
uid: this.props.user.data.uid,
token: this.token,
platform: 5,
video_id: videoList[activeIndex]['id'],
course_id: this.state.courseId,
v_course_id: vCourseId,
is_live: 0,
}))
}
if(!this.timer) {
this.setupTimer();
}
})
this.player.on('ratechange', () => {
this.currentPlaybackRate = this.player.playbackRate()
this.sendWatchTime(this.watchSec, this.previousPlaybackRate)
this.count = this.watchSec = 0
this.previousPlaybackRate = this.currentPlaybackRate
})
this.player.on('ended', () => {
this.sendWatchTime(this.watchSec, this.currentPlaybackRate);
this.count = this.watchSec = 0;
this.countSchedule(); // 计算进度 -- 播放完毕
// 返现课程才出现打卡记录
if(this.state.course.is_aist) {
this.getShareProgressInfo()
}
clearInterval(this.timer);
this.timer = null;
})
} }
let ctype = 0;
sendLastRecord = () => { if (course.is_aist) {
http.post(`${API.home}/m/course/record_last_video`, { ctype = 2;
v_course_id: this.state.course['v_course_id'],
video_id: this.state.videoList[this.state.activeIndex].id
})
} }
// 计算进度 根据ctype判断 课程类型 0-视频 1-直播 2-AI特训营
componentWillUnmount() { this.sendMessage({
this.player && this.player.dispose() mtype: 'count_schedule',
uid: this.props.user.data.uid,
clearInterval(this.timer) token: this.token,
this.timer = null; platform: 5,
this.ws && this.ws.close() video_id: videoList[activeIndex]['id'],
this.ws = null course_id: this.state.courseId,
v_course_id: vCourseId,
clearInterval(this.recordTimer) ctype: ctype,
this.recordSocket && this.recordSocket.close() })
this.recordSocket = null
}
// 发送时间消息
sendWatchTime = (sec, rate) => {
const {videoList, activeIndex, vCourseId, course = {}} = this.state
// 免费课程不发送
// if (Number(course.course_id) === 0 || course.course_id === '') {
// return;
// }
// 时间为0 不发送消息
if (Number(sec) === 0) {
return;
} }
let ctype = 0;
// 选择新的视频 if (course.is_aist) {
selectVideo = index => { ctype = 2;
if (index === this.state.activeIndex) { }
return // 时间足够不发送
// if(this.timeEnough) {
// return;
// }
this.sendMessage({
mtype: 'watch_time',
rate,
time: sec,
video_id: videoList[activeIndex]['id'],
course_id: this.state.courseId,
v_course_id: vCourseId,
uid: this.props.user.data.uid,
token: this.token,
platform: 5,
position: parseInt(this.player.currentTime()),
ctype: ctype,
})
}
setupTimer = () => {
this.count = 0
this.watchSec = 0
clearInterval(this.timer)
this.timer = null;
this.timer = setInterval(() => {
if (this.player && this.player.player()) {
if (this.count === 5) {
this.sendWatchTime(this.watchSec, this.currentPlaybackRate)
this.count = this.watchSec = 0
} else {
!this.player.paused() && this.watchSec++
!this.player.paused() && this.count++
} }
console.log('selectVideo 先发送时间 再发送进度 在重置定时器'); }
this.isCurrentVideoFirstPlay = true; // 切换视频则重置这个变量 因为新视频肯定是首次播放 }, 1000)
this.sendWatchTime(this.watchSec, this.currentPlaybackRate)
this.countSchedule(); // 计算进度 -- 选择新视频(可能是M端特有的) }
// 初始化视频播放器
initializePlayer = () => {
window.HELP_IMPROVE_VIDEOJS = false;
this.player = videojs(this.video, {
controls: true,
preload: 'auto',
bigPlayButton: false,
textTrackDisplay: false,
posterImage: false,
errorDisplay: false,
playbackRates: ['0.75', '1', '1.5', '2'],
controlBar: {
pictureInPictureToggle: false
}
})
this.player.addChild('CustomPlayButtonCover')
this.player.on('play', () => {
const {videoList, activeIndex, vCourseId, course = {}} = this.state
// 当视频播放时 看是否是第一次播放(初次进入页面 刷新页面 切换视频 都是第一次播放 需要获取上次的播放时间)
if (this.isCurrentVideoFirstPlay) {
// 当某些原因导致视频暂停时(用户暂停 网络不好等) 再播放时不需要发送
this.isCurrentVideoFirstPlay = false;
// 发送消息 recent_learn
this.ws.send(JSON.stringify({
mtype: this.RECENTLEARN,
uid: this.props.user.data.uid,
token: this.token,
platform: 5,
video_id: videoList[activeIndex]['id'],
course_id: this.state.courseId,
v_course_id: vCourseId,
is_live: 0,
}))
}
if (!this.timer) {
this.setupTimer(); this.setupTimer();
}
this.setState( })
{ this.player.on('ratechange', () => {
activeIndex: index this.currentPlaybackRate = this.player.playbackRate()
}, this.sendWatchTime(this.watchSec, this.previousPlaybackRate)
() => { this.count = this.watchSec = 0
this.previousPlaybackRate = this.currentPlaybackRate
if (this.hasAuth(this.state.activeIndex)) { })
this.setPlayerSrc(this.state.videoList[index]['play_url']) this.player.on('ended', () => {
this.sendLastRecord() this.sendWatchTime(this.watchSec, this.currentPlaybackRate);
this.playVideo() this.count = this.watchSec = 0;
} else { this.countSchedule(); // 计算进度 -- 播放完毕
this.getCoursePrice(); // 返现课程才出现打卡记录
} if (this.state.course.is_aist) {
} this.getShareProgressInfo()
); }
} clearInterval(this.timer);
this.timer = null;
getLastVideoIndex = lastIndex => { if (this.state.limitFreePopup.is_free) {
return this.state.videoList.findIndex(item => item.id == lastIndex) this.setState({
showLimitFreePopup: true
})
}
})
}
sendLastRecord = () => {
http.post(`${API.home}/m/course/record_last_video`, {
v_course_id: this.state.course['v_course_id'],
video_id: this.state.videoList[this.state.activeIndex].id
})
}
componentWillUnmount() {
this.player && this.player.dispose()
clearInterval(this.timer)
this.timer = null;
this.ws && this.ws.close()
this.ws = null
clearInterval(this.recordTimer)
this.recordSocket && this.recordSocket.close()
this.recordSocket = null
}
// 选择新的视频
selectVideo = index => {
if (index === this.state.activeIndex) {
return
} }
this.isCurrentVideoFirstPlay = true; // 切换视频则重置这个变量 因为新视频肯定是首次播放
getVideoList = () => { this.sendWatchTime(this.watchSec, this.currentPlaybackRate)
let url = ''; this.countSchedule(); // 计算进度 -- 选择新视频(可能是M端特有的)
if (getParam('video_id')) { this.setupTimer();
url = `${API.home}/m/course/play/${this.courseID + '?video_id=' + getParam('video_id')}`
http.post(`${API['base-api']}/sys/get_class_audition`, { this.setState(
video_id: getParam('video_id') {
}) activeIndex: index
},
() => {
if (this.hasAuth(this.state.activeIndex)) {
this.setPlayerSrc(this.state.videoList[index]['play_url'])
this.sendLastRecord()
this.playVideo()
} else { } else {
url = `${API.home}/m/course/play/${this.courseID}` this.getCoursePrice();
} }
http.get(url).then(res => { }
const {data = {}, code} = res.data; );
if (code === 200) { }
this.setState(
state => ({ getLastVideoIndex = lastIndex => {
videoList: data['lessons'], return this.state.videoList.findIndex(item => item.id == lastIndex)
currentVideoSrc: data['lessons'][state.activeIndex]['play_url'], }
course: data.course,
courseId: data.course['course_id'], getVideoList = () => {
vCourseId: data.course['v_course_id'], let url = '';
title: data.course['course_title'], if (getParam('video_id')) {
isLoading: false url = `${API.home}/m/course/play/${this.courseID + '?video_id=' + getParam('video_id')}`
}), http.post(`${API['base-api']}/sys/get_class_audition`, {
this.playSetup video_id: getParam('video_id')
) })
} else { } else {
Toast.info(data.msg) url = `${API.home}/m/course/play/${this.courseID}`
}
}
)
} }
http.get(url).then(res => {
playSetup = () => { const {data = {}, code} = res.data;
// is_aist,是否AI特训营 if (code === 200) {
const {course = {}} = this.state; this.setState(
// if (Number(course.course_id) === 0 || course.course_id === '') { state => ({
// console.log('免费课程 拦截'); videoList: data['lessons'],
// }else{ currentVideoSrc: data['lessons'][state.activeIndex]['play_url'],
let _this = this; course: data.course,
this.setupWS(); courseId: data.course['course_id'],
this.setupTimer(); vCourseId: data.course['v_course_id'],
let scheduleTime = setTimeout(function () { title: data.course['course_title'],
clearTimeout(scheduleTime); isLoading: false
scheduleTime = null; }),
_this.countSchedule(); // 刚进入页面的时候 就计算进度 先获取视频列表getVideoList 获取列表后 播放选择的视频 然后计算进度 this.playSetup
}, 1000); )
// } this.getLimitFreePopup(data.course.course_id)
let index = this.getLastVideoIndex(course.last_video_id); } else {
index = index >= 0 ? index : 0; Toast.info(data.msg)
this.setState( }
{ }
activeIndex: index )
}, }
() => {
if (this.lessonAvailable(index)) { playSetup = () => {
if (this.hasAuth(index)) { // is_aist,是否AI特训营
Promise.resolve().then(() => { const {course = {}} = this.state;
this.initializePlayer() // if (Number(course.course_id) === 0 || course.course_id === '') {
this.playWithAuth() // }else{
}) let _this = this;
} else { this.setupWS();
this.getCoursePrice(); this.setupTimer();
} let scheduleTime = setTimeout(function () {
} else { clearTimeout(scheduleTime);
alert('暂无视频', '', [{ scheduleTime = null;
text: 'OK', _this.countSchedule(); // 刚进入页面的时候 就计算进度 先获取视频列表getVideoList 获取列表后 播放选择的视频 然后计算进度
onPress: () => { }, 1000);
this.props.history.push('/') // }
} let index = this.getLastVideoIndex(course.last_video_id);
}]) index = index >= 0 ? index : 0;
} this.setState(
{
activeIndex: index
},
() => {
if (this.lessonAvailable(index)) {
if (this.hasAuth(index)) {
Promise.resolve().then(() => {
this.initializePlayer()
this.playWithAuth()
})
} else {
this.getCoursePrice();
}
} else {
alert('暂无视频', '', [{
text: 'OK',
onPress: () => {
this.props.history.push('/')
} }
); }])
}
}
);
} }
setPlayerSrc = src => { setPlayerSrc = src => {
if (!this.player) { if (!this.player) {
this.initializePlayer() this.initializePlayer()
}
this.player.src({
src,
type: 'application/x-mpegURL'
})
} }
this.player.src({
src,
type: 'application/x-mpegURL'
})
}
playVideo = () => { playVideo = () => {
this.player.ready(() => { this.player.ready(() => {
this.player.play() this.player.play()
}) })
} }
getDatumCatalog() { getDatumCatalog() {
http.get(`${API.home}/m/course/data/${this.courseID}`) http.get(`${API.home}/m/course/data/${this.courseID}`)
.then(res => { .then(res => {
const data = res.data const data = res.data
if (data.code === 200) { if (data.code === 200) {
this.setState({ this.setState({
datum: data.data datum: data.data
}) })
} else { } else {
Toast.info(data.msg) Toast.info(data.msg)
} }
}) })
} }
lessonAvailable = index => {
return this.state.videoList[index]['video_size'] !== 0
}
getCoursePrice = () => {
const {course = {}} = this.state;
http.get(`${API.home}/sys/course/price/${course.course_id}`)
.then(res => {
const {data} = res
if (data.code === 200) {
this.setState({
salePrice: data.data['sale_price']
})
}
})
}
lessonAvailable = index => { playWithAuth = () => {
return this.state.videoList[index]['video_size'] !== 0 const {videoList, activeIndex} = this.state
}
getCoursePrice = () => { if (this.hasAuth(activeIndex)) {
const {course = {}} = this.state; this.setPlayerSrc(videoList[activeIndex]['play_url'])
http.get(`${API.home}/sys/course/price/${course.course_id}`)
.then(res => {
const {data} = res
if (data.code === 200) {
this.setState({
salePrice: data.data['sale_price']
})
}
})
} }
}
playWithAuth = () => { hasAuth = index => {
const {videoList, activeIndex} = this.state const {videoList} = this.state
if (this.hasAuth(activeIndex)) { let lesson = videoList[index]
this.setPlayerSrc(videoList[activeIndex]['play_url'])
}
}
hasAuth = index => { if (lesson['video_auth']) {
const {videoList} = this.state this.setState({
isAuth: true
})
return true
} else {
this.setState({
isAuth: false
})
return false
let lesson = videoList[index] }
}
getLimitFreePopup = id => {
http.post(`${API.home}/sys/popup`, {
course_id: id
})
.then(res => {
const {code, msg, data} = res.data
if (code === 200) {
const {courseId, limitFreePopupVideos} = this.state
this.setState({
limitFreePopup: data,
isShowNeverShowPopupOption: limitFreePopupVideos ? limitFreePopupVideos.includes(courseId) : false
})
if (lesson['video_auth']) {
this.setState({
isAuth: true
})
return true
} else { } else {
this.setState({ Toast.info(msg, 2, null, false)
isAuth: false
})
return false
} }
})
}
checkNeverShowLimitFreePopup = () => {
if (!this.state.limitFreeNoPromptChecked) {
return
} }
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() {
let {match, location, history} = this.props
const {videoList, activeIndex, isAuth, salePrice, course, singleBox, singleType} = this.state;
let toHref = '';
if (location.state && location.state.to && location.state.to === 'detail') {
toHref = `/detail?id=${course.course_id}`
} }
return ( })
<div className='play'> }
<HeaderBar title={this.state.title} arrow={true} toHref={() => {
toHref ? history.push( render() {
toHref, let {match, location, history} = this.props
{ const {
to: 'classify' videoList,
} activeIndex,
) : history.go(-1) isAuth,
}}/> salePrice,
<Loading isLoading={this.state.isLoading}> course,
<div className="video"> singleBox,
<video className={'video-js'} ref={el => this.video = el} singleType,
webkit-playsinline="true" showLimitFreePopup,
playsInline={true} limitFreePopup,
x-webkit-airplay="allow" isShowNeverShowPopupOption
x5-video-player-type="h5"> } = this.state;
<source src={'/'} type='application/x-mpegURL'/> let toHref = '';
</video> if (location.state && location.state.to && location.state.to === 'detail') {
{ toHref = `/detail?id=${course.course_id}`
!isAuth && !!videoList[activeIndex]['is_class'] && ( }
<div className="purchase-box"> return (
<div className='hint'>您尚未购买该课时,请购买后学习。</div> <div className='play'>
<div className='btns'> <HeaderBar title={this.state.title} arrow={true} toHref={() => {
<button toHref ? history.push(
type='button' toHref,
onClick={this.tobuy} {
className='purchase-class' to: 'classify'
> }
¥{salePrice} 购买课程 ) : history.go(-1)
</button> }}/>
<button <Loading isLoading={this.state.isLoading}>
type='button' <div className="video">
onClick={this.toSingleset.bind(this, videoList[activeIndex])} <video className={'video-js'} ref={el => this.video = el}
className='purchase-episode' webkit-playsinline="true"
> playsInline={true}
¥{videoList.length && videoList[activeIndex]['class_price']} 购买单集 x-webkit-airplay="allow"
</button> x5-video-player-type="h5">
</div> <source src={'/'} type='application/x-mpegURL'/>
</div> </video>
) {
} !isAuth && !!videoList[activeIndex]['is_class'] && (
{ <div className="purchase-box">
!isAuth && !!course.is_aist && ( <div className='hint'>您尚未购买该课时,请购买后学习。</div>
<div className="is-aist-box"> <div className='btns'>
<i className={'iconfont iconiconfront-21'}></i> <button
<p className={'time'}>{videoList[activeIndex]['aist_start_time']}</p> type='button'
<p className={'time'}>请耐心等待...</p> onClick={this.tobuy}
</div> className='purchase-class'
) >
} ¥{salePrice} 购买课程
</div> </button>
<div className='tab'> <button
<div> type='button'
<NavLink to={{pathname: `${match.url}/video`, search: `?id=${this.courseID}`}} onClick={this.toSingleset.bind(this, videoList[activeIndex])}
replace className='purchase-episode'
activeClassName='active' >
>视频</NavLink> ¥{videoList.length && videoList[activeIndex]['class_price']} 购买单集
</div> </button>
<div> </div>
<NavLink to={{pathname: `${match.url}/datum`, search: `?id=${this.courseID}`}} </div>
replace )
activeClassName='active' }
>资料</NavLink> {
</div> !isAuth && !!course.is_aist && (
</div> <div className="is-aist-box">
<i className={'iconfont iconiconfront-21'}></i>
{/*单集购买*/} <p className={'time'}>{videoList[activeIndex]['aist_start_time']}</p>
{ <p className={'time'}>请耐心等待...</p>
singleBox && </div>
<Single )
courseId={course.course_id} }
singleBox={this.state.singleBox} </div>
boxHide={this.boxHide} <div className='tab'>
data={this.state.singMess} <div>
singleType={this.state.singleType} <NavLink to={{pathname: `${match.url}/video`, search: `?id=${this.courseID}`}}
vcourseId={course.v_course_id} replace
videoId={this.state.singMess.video_id} activeClassName='active'
check={this.check} >视频</NavLink>
title={this.state.singMess.course_tile}/> </div>
} <div>
{/* 单集购买成功 */} <NavLink to={{pathname: `${match.url}/datum`, search: `?id=${this.courseID}`}}
{ replace
singleType !== 1 && activeClassName='active'
<SingleSuccess >资料</NavLink>
courseId={course.course_id} </div>
boxHide={this.boxHide} </div>
data={this.state.singMess}
singleType={singleType} {/*单集购买*/}
vcourseId={course.v_course_id} {
videoId={this.state.singMess.video_id} singleBox &&
nowPrice={this.state.nowPrice} <Single
laterPrice={this.state.laterPrice} courseId={course.course_id}
/> singleBox={this.state.singleBox}
} boxHide={this.boxHide}
data={this.state.singMess}
</Loading> singleType={this.state.singleType}
<Switch> vcourseId={course.v_course_id}
<Redirect exact from={'/play'} to={{ videoId={this.state.singMess.video_id}
pathname: '/play/video', check={this.check}
search: location.search title={this.state.singMess.course_tile}/>
}}/> }
<Route {/* 单集购买成功 */}
path={`${match.path}/video`} {
render={props => { singleType !== 1 &&
return ( <SingleSuccess
<VideoCatalog courseId={course.course_id}
activeIndex={this.state.activeIndex} boxHide={this.boxHide}
selectVideo={this.selectVideo} data={this.state.singMess}
videoCatalog={videoList} singleType={singleType}
isAist={course.is_aist} vcourseId={course.v_course_id}
{...props} videoId={this.state.singMess.video_id}
/> nowPrice={this.state.nowPrice}
); laterPrice={this.state.laterPrice}
}} />
/> }
<Route path={`${match.path}/datum`} render={props => {
return <DatumCatalog {...props} datum={this.state.datum}/> </Loading>
}}/> <Switch>
</Switch> <Redirect exact from={'/play'} to={{
<Route render={props => { pathname: '/play/video',
return this.state.vCourseId ? <Recommendation {...props} vCourseId={this.state.vCourseId}/> search: location.search
: null }}/>
}}/> <Route
<ProgressShareModal isShow={this.state.isShowShareModal} path={`${match.path}/video`}
closeShareModal={() => this.setState({isShowShareModal: false})} render={props => {
data={this.state.shareData} return (
<VideoCatalog
activeIndex={this.state.activeIndex}
selectVideo={this.selectVideo}
videoCatalog={videoList}
{...props}
/> />
);
}}
/>
<Route path={`${match.path}/datum`} render={props => {
return <DatumCatalog {...props} datum={this.state.datum}/>
}}/>
</Switch>
<Route render={props => {
return this.state.vCourseId ? <Recommendation {...props} vCourseId={this.state.vCourseId}/>
: null
}}/>
<ProgressShareModal isShow={this.state.isShowShareModal}
closeShareModal={() => this.setState({isShowShareModal: false})}
data={this.state.shareData}
/>
{
showLimitFreePopup &&
<div className={'limit-free-cover'}>
<div className="free-popup">
<div className="title">
<span>{limitFreePopup.pop_descbition}</span>
</div>
<div className={'des'}>
<img className="qrcode"
src={limitFreePopup.wechat_img} alt=''/>
<span>长按/扫码识别</span>
<span>添加时请备注<span>{course.course_id}</span>哦</span>
<div className="no-prompt">
{
isShowNeverShowPopupOption &&
<label htmlFor="no-prompt">
<span
className={`checkbox-label ${this.state.limitFreeNoPromptChecked ? 'checked' : 'unchecked'}`}>
<i className={'iconfont iconiconfront-73'}/>
</span>
<input type="checkbox" id={'no-prompt'} onChange={(e) => {
this.setState({
limitFreeNoPromptChecked: e.target.checked
})
}}/>
<span>本课程不再提示</span>
</label>
}
</div>
</div>
<i className={'close-btn iconfont iconiconfront-2'} onClick={() => {
this.setState({
showLimitFreePopup: false,
isShowNeverShowPopupOption: true
})
const {courseId, limitFreePopupVideos} = this.state
localStorage.setItem('limit-free-popup-videos', JSON.stringify(
limitFreePopupVideos ? [...limitFreePopupVideos, courseId] : [courseId]
))
this.checkNeverShowLimitFreePopup()
}}/>
</div> </div>
); </div>
} }
</div>
);
}
} }
export default connect( export default connect(
state => ({user: state.user}), state => ({user: state.user}),
null null
)(Video); )(Video);
$tabHeight: 44px; $tabHeight: 44px;
.play { .play {
.video { .video {
width: 100%; width: 100%;
height: 215px; height: 215px;
background-color: $black; background-color: $black;
position: relative; position: relative;
.video-js { .video-js {
width: 100%; width: 100%;
height: 100%; height: 100%;
.vjs-custom-play-button-cover {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
.vjs-custom-play-button {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 27px;
height: 27px;
background: url("./images/play.png") no-repeat;
background-size: contain;
}
}
&.vjs-has-started{
.vjs-custom-play-button-cover{
bottom: 2.9em;
}
}
&.vjs-playing {
.vjs-custom-play-button-cover {
display: none;
}
}
}
.purchase-box { .vjs-custom-play-button-cover {
width: 100%; position: absolute;
height: 100%; top: 0;
position: absolute; bottom: 0;
left: 0; left: 0;
top: 0; right: 0;
background-color: rgba(0, 0, 0, 0.8); background: rgba(0, 0, 0, 0.5);
display: flex;
flex-flow: column;
justify-content: center; .vjs-custom-play-button {
align-items: center; position: absolute;
top: 50%;
.hint { left: 50%;
font-size: $font_14; transform: translate(-50%, -50%);
color: $white; width: 27px;
margin-bottom: 20px; height: 27px;
} background: url("./images/play.png") no-repeat;
background-size: contain;
@mixin button {
display: block;
-webkit-appearance: none;
outline: none;
border: none;
background-color: transparent;
border-radius: 5px;
line-height: 30px;
font-size: 13px;
padding: 0 9px;
}
.btns {
width: 100%;
padding: 0 60px;
display: flex;
justify-content: space-around;
}
.purchase-class {
@include button;
background-color: $white;
color: $color_FF4000;
}
.purchase-episode {
@include button;
background-color: $bg_FF4000;
color: $white;
}
} }
}
.is-aist-box { &.vjs-has-started {
width: 100%; .vjs-custom-play-button-cover {
height: 100%; bottom: 2.9em;
position: absolute;
left: 0;
top: 0;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
color: #fff;
i {
font-size: 34px;
}
.time {
font-size: 16px;
}
} }
}
video {
width: 100%; &.vjs-playing {
height: 100%; .vjs-custom-play-button-cover {
display: none;
} }
}
} }
.tab { .purchase-box {
height: $tabHeight; width: 100%;
max-height: $tabHeight; height: 100%;
line-height: $tabHeight; position: absolute;
text-align: center; left: 0;
background: #fff; top: 0;
flex: 1 0 auto; background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
.hint {
font-size: $font_14;
color: $white;
margin-bottom: 20px;
}
@mixin button {
display: block;
-webkit-appearance: none;
outline: none;
border: none;
background-color: transparent;
border-radius: 5px;
line-height: 30px;
font-size: 13px;
padding: 0 9px;
}
.btns {
width: 100%;
padding: 0 60px;
display: flex; display: flex;
justify-content: center; justify-content: space-around;
}
.purchase-class {
@include button;
background-color: $white;
color: $color_FF4000;
}
.purchase-episode {
@include button;
background-color: $bg_FF4000;
color: $white;
}
}
& > div { .is-aist-box {
flex: 1 0 auto; width: 100%;
} height: 100%;
position: absolute;
left: 0;
top: 0;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
color: #fff;
i {
font-size: 34px;
}
.time {
font-size: 16px;
}
}
a { video {
display: inline-block; width: 100%;
height: $tabHeight; height: 100%;
font-size: $font_16; }
border-bottom: 1px solid transparent; }
.tab {
height: $tabHeight;
max-height: $tabHeight;
line-height: $tabHeight;
text-align: center;
background: #fff;
flex: 1 0 auto;
display: flex;
justify-content: center;
& > div {
flex: 1 0 auto;
}
&.active { a {
border-bottom: 1px solid $active; display: inline-block;
} height: $tabHeight;
} font-size: $font_16;
border-bottom: 1px solid transparent;
&.active {
border-bottom: 1px solid $active;
}
} }
}
.active { .active {
color: $active; color: $active;
.iconiconfront-74 { .iconiconfront-74 {
color: $color_555; color: $color_555;
} }
}
.progress-share-modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 290px;
height: 332px;
padding: 18px 15px;
background: url("./images/progress-share-bg.png");
background-size: contain;
& > .title {
font-size: 21px;
color: #00656F;
line-height: 30px;
text-align: center;
margin-bottom: 20px;
} }
.progress-share-modal { .progress-container {
position: absolute; display: flex;
top: 50%; justify-content: space-between;
left: 50%; margin-bottom: 20px;
transform: translate(-50%, -50%);
width: 290px; li {
height: 332px; flex: 1;
padding: 18px 15px;
background: url("./images/progress-share-bg.png"); .title {
background-size: contain; font-size: 14px;
color: #00838F;
& > .title { line-height: 20px;
font-size: 21px; text-align: center;
flex: 1;
margin-bottom: 10px;
}
.number {
font-size: 15px;
color: #00656F;
text-align: center;
.num {
font-size: 33px;
color: #00656F; color: #00656F;
line-height: 30px; }
text-align: center;
margin-bottom: 20px;
} }
}
}
.progress-container { .share-container {
display: flex; .title {
justify-content: space-between; position: relative;
margin-bottom: 20px; text-align: center;
font-size: 14px;
li { color: #00838F;
flex: 1; margin-bottom: 25px;
.title { &::before {
font-size: 14px; position: absolute;
color: #00838F; top: 50%;
line-height: 20px; left: 30px;
text-align: center; transform: translateY(-50%);
flex: 1; content: '';
margin-bottom: 10px; display: block;
} width: 70px;
height: 1px;
.number { background: #77c4bf;
font-size: 15px;
color: #00656F;
text-align: center;
.num {
font-size: 33px;
color: #00656F;
}
}
}
} }
.share-container { &::after {
.title { position: absolute;
position: relative; top: 50%;
text-align: center; right: 30px;
font-size: 14px; transform: translateY(-50%);
color: #00838F; content: '';
margin-bottom: 25px; display: block;
width: 70px;
&::before { height: 1px;
position: absolute; background: #77c4bf;
top: 50%;
left: 30px;
transform: translateY(-50%);
content: '';
display: block;
width: 70px;
height: 1px;
background: #77c4bf;
}
&::after {
position: absolute;
top: 50%;
right: 30px;
transform: translateY(-50%);
content: '';
display: block;
width: 70px;
height: 1px;
background: #77c4bf;
}
}
ul {
display: flex;
justify-content: space-around;
padding: 0 20px;
text-align: center;
li {
font-size: 12px;
color: #00838F;
.iconfont {
font-size: 40px;
color: #00838f;
}
}
}
} }
}
ul {
display: flex;
justify-content: space-around;
padding: 0 20px;
text-align: center;
.close { li {
position: absolute; font-size: 12px;
left: 50%; color: #00838F;
transform: translateX(-50%);
bottom: -63px; .iconfont {
color: #fff; font-size: 40px;
font-size: 30px; color: #00838f;
}
} }
}
}
.close {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -63px;
color: #fff;
font-size: 30px;
}
&-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
touch-action: none;
z-index: 100;
}
}
}
.limit-free-cover {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0, 0, 0, .8);
z-index: 999;
}
&-wrapper { .free-popup {
position: fixed; position: absolute;
top: 0; top: 50%;
left: 0; left: 50%;
width: 100%; transform: translate(-50%, -50%);
height: 100%; width: 290px;
background: rgba(0, 0, 0, 0.5); height: 366px;
touch-action: none; border-radius: 5px !important;
z-index: 100; padding: 0 !important;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/time_limited_free/M/popup-bg.png") !important;
background-size: cover !important;
.title {
display: flex;
align-items: center;
height: 125px;
padding: 0 20px;
color: #fff !important;
font-size: 15px;
}
.des {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-top: 20px;
.qrcode {
margin-bottom: 10px;
width: 118px;
height: 118px;
}
& > span:nth-of-type(1) {
color: #666;
font-size: 13px;
margin-bottom: 10px;
}
& > span:nth-of-type(2) {
color: #333;
font-size: 15px;
margin-bottom: 14px;
}
span span {
color: #FF2121;
}
.no-prompt {
label {
position: relative;
padding-left: 21px;
height: 14px;
}
input, .checkbox-label {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 13px;
height: 13px;
-webkit-appearance: none;
outline: 0;
background: #fff;
}
input {
opacity: 0;
}
.checkbox-label {
border: 1px solid rgba(84, 92, 100, .6);
border-radius: 1px;
left: -1px;
box-sizing: border-box;
.iconfont {
color: #fff;
font-size: 12px;
} }
}
span {
color: #545C64;
font-size: 13px;
margin-bottom: 0;
line-height: 14px;
}
.checked {
background: #09f;
}
} }
}
.close-btn {
position: absolute;
bottom: -44px;
left: 50%;
transform: translateX(-50%);
font-size: 26px;
color: #fff;
}
} }
...@@ -299,4 +299,10 @@ export default [ ...@@ -299,4 +299,10 @@ export default [
exact: true, exact: true,
component: loadable(() => import('@/components/college/courseList')) component: loadable(() => import('@/components/college/courseList'))
}, },
//限时免费落地页
{
path:'/free',
exact: true,
component: loadable(() => import(/*limit-free*/'@/components/limit-free'))
}
] ]
import jsCookie from "js-cookie"; import jsCookie from "js-cookie";
import {
differenceInDays,
differenceInHours,
differenceInMinutes,
differenceInSeconds
} from 'date-fns'
export const getParam = (key, str) => { export const getParam = (key, str) => {
const _s = str ? str : location.href; const _s = str ? str : location.href;
const re = new RegExp(`(?:\\?|#|&)(${key})=([^=&#\\?]+)`, 'ig'); const re = new RegExp(`(?:\\?|#|&)(${key})=([^=&#\\?]+)`, 'ig');
let found; let found;
return (found = re.exec(_s)) ? found[2] : null; return (found = re.exec(_s)) ? found[2] : null;
} }
const html = content => ({__html: htmlDecode(content)}) const html = content => ({
__html: htmlDecode(content)
})
const htmlDecode = content => { const htmlDecode = content => {
let e = document.createElement('div'); let e = document.createElement('div');
e.innerHTML = content; e.innerHTML = content;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue; return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
} }
//加载网易易盾辅助函数 //加载网易易盾辅助函数
function getTimestamp(msec) { function getTimestamp(msec) {
msec = !msec && msec !== 0 ? msec : 1 msec = !msec && msec !== 0 ? msec : 1
return parseInt((new Date()).valueOf() / msec, 10) return parseInt((new Date()).valueOf() / msec, 10)
} }
function loadScript(src, cb) { function loadScript(src, cb) {
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')
cb = cb || function () { cb = cb || function () {
} }
script.type = 'text/javascript' script.type = 'text/javascript'
script.src = src script.src = src
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
cb(script) cb(script)
}
} }
}
script.onload = function () { script.onload = function () {
this.onload = null this.onload = null
cb(script) cb(script)
} }
head.appendChild(script) head.appendChild(script)
} }
function initCaptcha(cb) { function initCaptcha(cb) {
if (window.initNECaptcha) { if (window.initNECaptcha) {
cb() cb()
} else { } else {
const url = '//cstaticdun.126.net/load.min.js' + '?t=' + getTimestamp(1 * 60 * 1000) const url = '//cstaticdun.126.net/load.min.js' + '?t=' + getTimestamp(1 * 60 * 1000)
loadScript(url, cb) loadScript(url, cb)
} }
} }
export const is_weixin = () => { export const is_weixin = () => {
var ua = window.navigator.userAgent.toLowerCase(); var ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger') { if (ua.match(/MicroMessenger/i) == 'micromessenger') {
return true; return true;
} }
return false; return false;
} }
function validateTel(tel) { function validateTel(tel) {
return /^1[3-9](\d{9})$/.test(tel) return /^1[3-9](\d{9})$/.test(tel)
} }
function validateEmail(email) { function validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase()); return re.test(String(email).toLowerCase());
} }
const browser = (function () { const browser = (function () {
const ua = navigator.userAgent const ua = navigator.userAgent
return { return {
isWeixin: /MicroMessenger/i.test(ua), isWeixin: /MicroMessenger/i.test(ua),
isAndroid: /Android/i.test(ua), isAndroid: /Android/i.test(ua),
isIOS: /\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(ua), isIOS: /\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(ua),
isIPad: /iPad/i.test(ua), isIPad: /iPad/i.test(ua),
isAndroidApp: /Android/i.test(ua) && getParam('version'), isAndroidApp: /Android/i.test(ua) && getParam('version'),
isIOSApp: /iPhone/i.test(ua) && getParam('version') isIOSApp: /iPhone/i.test(ua) && getParam('version')
} }
})() })()
const isLogin = (function () { const isLogin = (function () {
return jsCookie.get('uid') && jsCookie.get('token') return jsCookie.get('uid') && jsCookie.get('token')
})() })()
const dateCountDown = (later, earlier) => {
const d = differenceInDays(later, earlier)
const h = differenceInHours(later, earlier) % 24
const m = differenceInMinutes(later, earlier) % 60
const s = differenceInSeconds(later, earlier) % 60
return {
d,
h,
m,
s
}
}
export {default as http} from './http'
export {default as wxShare} from './wechat/share' export {
export {html, initCaptcha, validateTel, validateEmail, browser, isLogin} default as http
export {default as SendMessageToApp} from './app' }
from './http'
export {
default as wxShare
}
from './wechat/share'
export {
html,
initCaptcha,
validateTel,
validateEmail,
browser,
isLogin,
dateCountDown
}
export {
default as SendMessageToApp
}
from './app'
\ 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