Commit d3a588c3 by zhanghaozhe

Merge branch 'limit-free'

# Conflicts:
#	src/components/video/index.js
parents 9462f7d6 16faa68d
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1568272104473'); /* IE9 */
src: url('iconfont.eot?t=1568272104473#iefix') format('embedded-opentype'), /* IE6-IE8 */
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.ttf?t=1568272104473') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1568272104473#iconfont') format('svg'); /* iOS 4.1- */
src: url('iconfont.eot?t=1583394769931'); /* IE9 */
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('iconfont.woff?t=1583394769931') format('woff'),
url('iconfont.ttf?t=1583394769931') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1583394769931#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
......@@ -15,64 +15,136 @@
-moz-osx-font-smoothing: grayscale;
}
.iconyanjing:before {
content: "\e667";
.iconRectangleCopy4:before {
content: "\e6a5";
}
.iconremen:before {
content: "\e642";
.icontijikongjian:before {
content: "\e89f";
}
.iconzhaopin:before {
content: "\e67e";
.iconshouye:before {
content: "\e8b9";
}
.iconshouji:before {
content: "\e66d";
.iconyonghu:before {
content: "\e8c8";
}
.iconqiye1:before {
content: "\e669";
.iconall:before {
content: "\e6ef";
}
.icon-jingsai:before {
content: "\e67f";
.iconbofangyedianzan:before {
content: "\e687";
}
.iconerji:before {
content: "\e65f";
.iconbofang:before {
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 {
content: "\e682";
}
.iconcelluar:before {
content: "\e680";
}
.iconzhanghu_jiangjin:before {
content: "\e681";
}
.iconhuabei:before {
content: "\e78c";
.iconzhaopin:before {
content: "\e67e";
}
.iconyindao:before {
content: "\e72e";
.iconqiye1:before {
content: "\e669";
}
.iconpwd-hidden:before {
content: "\e668";
.icon-jingsai:before {
content: "\e67f";
}
.iconweixinzhifu:before {
content: "\e662";
.icongouwuche-xianxing:before {
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 {
content: "\e6cd";
}
.iconyouhuiquan:before {
content: "\e63c";
.iconshouji:before {
content: "\e66d";
}
.iconduanxin:before {
content: "\e66e";
}
.iconyanjing:before {
content: "\e667";
}
.iconpwd-hidden:before {
content: "\e668";
}
.icondianzan:before {
......@@ -83,8 +155,44 @@
content: "\ec8c";
}
.iconduanxin:before {
content: "\e66e";
.iconhuabei:before {
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 {
......@@ -479,79 +587,3 @@
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 {
height: 130px;
//height: 130px;
padding: 10px 10px 0;
position: relative;
......
......@@ -12,386 +12,393 @@ import { Toast } from 'antd-mobile'
import { connect } from "react-redux";
import TopSwiper from './TopSwiper'
import ExpandActiveToast from './expandActiveToast'
import CourseBase from '@/common/course-base'
import { switchTab } from "@components/study/myCourses/actions"
// const animateTypes = Swiper.animateTypes
@connect(state => ({
user: state.user
user: state.user
}))
class Index extends Component {
constructor(props) {
super(props)
this.state = {
banner: [], // 首页banner
lives: [], //近期直播
modules: [], //首页课程模块儿
isShow: false,
islive: false,
roomMess: '',
tabdata: [
{
'src': require('./image/freeclass_icon.png'),
'name': '公开课',
'href': '/study/free-course'
},
{
'src': require('./image/jingpin_icon.png'),
'name': '精品特惠',
'href': '/preferential'
},
{
'src': require('./image/zjxj_icon.png'),
'name': '赚奖学金',
'href': '/scholarship'
},
{
'src': require('./image/mryt_icon.png'),
'name': '每日一题',
'href': '/examination'
},
{
'src': require('./image/shequ_icon.png'),
'name': '社区',
'href': 'https://ask.julyedu.com'
}
]
constructor(props) {
super(props)
this.state = {
banner: [], // 首页banner
lives: [], //近期直播
modules: [], //首页课程模块儿
isShow: false,
islive: false,
roomMess: '',
tabdata: [
{
'src': require('./image/freeclass_icon.png'),
'name': '公开课',
'href': '/study/free-course'
},
{
'src': require('./image/jingpin_icon.png'),
'name': '精品特惠',
'href': '/preferential'
},
{
'src': require('./image/zjxj_icon.png'),
'name': '赚奖学金',
'href': '/scholarship'
},
{
'src': require('./image/mryt_icon.png'),
'name': '每日一题',
'href': '/examination'
},
{
'src': require('./image/shequ_icon.png'),
'name': '社区',
'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>
// 点击近期直播课程弹出预约提示框
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})
}
<ExpandActiveToast/>
// 点击头部搜索跳转到搜索页面
toSearch() {
this.props.history.push('/search')
}
<div className='index-swiper'>
{
this.state.banner && this.state.banner.length > 0 &&
<TopSwiper bannerList={this.state.banner}/>
}
</div>
toCourseDetail = (id) => {
const {dispatch, history} = this.props;
// dispatch(getCourses(id, () => {
history.push(`/detail?id=${id}`);
return false;
// }));
}
<div className="tabbox">
<ul>
{
this.state.tabdata.map((item, index) => {
return (
<li key={index}>
<a href={item.href}>
<img src={item.src} alt=""/>
<span>{item.name}</span>
</a>
</li>
)
})
}
</ul>
</div>
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>
<p className="borderTop"/>
<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.banner && this.state.banner.length > 0 &&
<TopSwiper bannerList={this.state.banner}/>
}
</div>
{
(this.state.modules && this.state.modules.length > 0) ? this.state.modules.map((item, index) => {
return (
<div key={index}>
<CourseList
modules={item}
toDetail={this.toCourseDetail}
/>
<p className="borderTop"/>
</div>
)
}) : null
}
<div className="tabbox">
<ul>
{
this.state.tabdata.map((item, index) => {
return (
<li key={index}>
<a href={item.href}>
<img src={item.src} alt=""/>
<span>{item.name}</span>
</a>
</li>
)
})
}
</ul>
</div>
<div className="category all-course">
<Link to='/classify'>
<p>查看全部课程</p>
<span>数学基础、数学结构、大数据实战、Python...</span>
</Link>
</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>
<ScrollBox
livesList={this.state.lives}
liveCourse={this.liveCourse}
/>
</div> : null
}
// 课程模块儿公共组件
// 课程数量是奇数第一个课程需要横着展示沾满一行,课程数量是偶数一行显示两个
function CourseList({modules, toDetail}) {
{
(this.state.modules && this.state.modules.length > 0) ? this.state.modules.map((item, index) => {
return (
<div key={index}>
<CourseList
modules={item}
toDetail={this.toCourseDetail}
/>
<p className="borderTop"/>
</div>
)
}) : null
}
let filterList = []
let isOdd = modules.list.length % 2 === 0
<div className="category all-course">
<Link to='/classify'>
<p>查看全部课程</p>
<span>数学基础、数学结构、大数据实战、Python...</span>
</Link>
</div>
if (modules.name === '限时免费') {
filterList = modules.list
} else {
// 数量为奇数时,第一个课程显示大图(如后台未上传,前台显示小图),课程数量为偶数时,均显示小图
{/* 直播间预约 */}
{
this.state.islive &&
<LiveRoom
isShow={this.state.isShow}
colseBox={this.colseBox}
roomMess={this.state.roomMess}
getIndexData={this.getIndexData}
/>
}
</div>
)
if (isOdd) {
filterList = modules.list
} else {
filterList = modules.list[0].course_img === modules.list[0].course_img_small ? modules.list : modules.list.slice(1)
}
}
}
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}) {
// 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 bottom = <Bottom course={item}/>
// 课程模块儿公共组件
// 课程数量是奇数第一个课程需要横着展示沾满一行,课程数量是偶数一行显示两个
function CourseList({modules, toDetail}) {
let isOdd = modules.list.length % 2 === 0
// 数量为奇数时,第一个课程显示大图(如后台未上传,前台显示小图),课程数量为偶数时,均显示小图
let filterList = ''
const status = item.is_limit_free ? null : <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>
)
}
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 {
filterList = modules.list[0].course_img === modules.list[0].course_img_small ? modules.list : modules.list.slice(1)
return <div className={'isbuy'}>已购买</div>
}
return (
<div className='category'>
<h2 className="title">{modules.name}</h2>
{
modules.show_more === 1 &&
<Link className="more" to='/classify'>更多 ></Link>
}
{
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>
)
} else {
return course.is_limit_free
? <LimitFree course={course}/>
: <p className="course-price">
<span className="new">¥{course.discounts_price}</span>
<span className="old">¥{course.price}</span>
</p>
}
}
//近期直播
function ScrollBox(props) {
return (
<div className='scroll-box'>
<ul className='scroll-list'>
{
props.livesList && props.livesList.length > 0 && props.livesList.map((item, index) => {
return (
<li key={index} className='scroll-item'
onClick={e => props.liveCourse(item)}>
<div className='item-box'>
{
item.live_status === 0 &&
<span className='no-start'>即将开始</span>
}
{
(item.live_status === 1 || item.live_status === 10) &&
<span className='start'>正在直播</span>
}
<img className="item-img" src={item.live_img} alt=""/>
<div className="item-content">
<h2 className="item-title">{item.live_title}</h2>
<p className="item-teacher">讲师:{item.live_teacher_name}</p>
{/*公开课需预约、付费课不需要预约*/}
{
(item.is_prepare || item.is_free === 0) && item.live_status === 0 &&
<p className="item-time">时间:{item.live_start_time}</p>
}
{
!item.is_prepare && item.live_status === 0 && item.is_free === 1 &&
<button className='item-btn'>预约</button>
}
{
(item.live_status === 1 || item.live_status === 10) &&
<button className='item-btn'>正在直播</button>
}
</div>
</div>
</li>
)
})
}
</ul>
</div>
)
return (
<div className='scroll-box'>
<ul className='scroll-list'>
{
props.livesList && props.livesList.length > 0 && props.livesList.map((item, index) => {
return (
<li key={index} className='scroll-item'
onClick={e => props.liveCourse(item)}>
<div className='item-box'>
{
item.live_status === 0 &&
<span className='no-start'>即将开始</span>
}
{
(item.live_status === 1 || item.live_status === 10) &&
<span className='start'>正在直播</span>
}
<img className="item-img" src={item.live_img} alt=""/>
<div className="item-content">
<h2 className="item-title">{item.live_title}</h2>
<p className="item-teacher">讲师:{item.live_teacher_name}</p>
{/*公开课需预约、付费课不需要预约*/}
{
(item.is_prepare || item.is_free === 0) && item.live_status === 0 &&
<p className="item-time">时间:{item.live_start_time}</p>
}
{
!item.is_prepare && item.live_status === 0 && item.is_free === 1 &&
<button className='item-btn'>预约</button>
}
{
(item.live_status === 1 || item.live_status === 10) &&
<button className='item-btn'>正在直播</button>
}
</div>
</div>
</li>
)
})
}
</ul>
</div>
)
}
export default WithTab(Index);
#chatBtn {
bottom: 60px!important;
bottom: 60px !important;
}
.index-box {
overflow: hidden;
background-color: $bg_fff;
......@@ -283,6 +284,20 @@
font-size: 16px;
color: $color_333;
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 {
......@@ -349,14 +364,17 @@
.isbuy {
display: inline-block;
margin-top: 15px;
width: 61px;
height: 18px;
background-color: $bg_active;
border-radius: 9px;
color: $white;
font-size: 12px;
color: $active;
font-size: 15px;
text-align: center;
line-height: 18px;
font-family: PingFang SC;
font-weight: 400;
}
.free {
color: $red;
font-size: 15px;
}
}
......@@ -511,7 +529,7 @@
text-align: center;
height: 47px;
button,a {
button, a {
width: 60px;
height: 27px;
background-color: $bg_active;
......@@ -524,7 +542,8 @@
margin-left: -30px;
bottom: 10px;
}
a{
a {
width: 90px;
line-height: 27px;
margin-left: -45px;
......@@ -740,9 +759,91 @@
// //.is-visible {
// // 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;
}
......
......@@ -10,160 +10,160 @@ import { StickyContainer, Sticky } from "react-sticky";
function stopScroll(e) {
e.preventDefault()
e.preventDefault()
}
@connect(({user}) => ({
user
user
}))
class Classify extends Component {
constructor(props) {
super(props)
this.state = {
ispull: false,
display: 'none',
arr: [{basics: []}, {advanced: []}],
allClass: [],
data: [],
activeTab: decodeURIComponent(getParam('name')),
isLoading: true,
top: 44
}
constructor(props) {
super(props)
this.state = {
ispull: false,
display: 'none',
arr: [{basics: []}, {advanced: []}],
allClass: [],
data: [],
activeTab: decodeURIComponent(getParam('name')),
isLoading: true,
top: 44
}
componentDidMount() {
this.getTabs()
this.getList()
}
const el = document.querySelector('.search-nav');
this.setState({
top: el.offsetHeight
});
}
componentDidMount() {
this.getTabs()
this.getList()
componentWillUnmount() {
document.removeEventListener('touchmove', stopScroll)
}
const el = document.querySelector('.search-nav');
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 => {
console.log(err)
_this.setState({
arr: arr2,
allClass: arr3
})
}
}
} else {
Toast.info(res.data.msg, 2)
}
// 获取课程接口
getList = () => {
const _this = this
_this.setState((state, props)=>({
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
})
}
})
.catch(err => {
console.log(err)
})
}
// 获取课程接口
getList = () => {
const _this = this
_this.setState((state, props) => ({
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查询
ontabclick = (tab) => {
this.props.history.push(`/courselist?id=${tab.id}&name=${tab.title}`)
this.getList()
this.setState({
activeTab: decodeURIComponent(getParam('name'))
});
}
// 点击横向滚动tab查询
ontabclick = (tab) => {
this.props.history.push(`/courselist?id=${tab.id}&name=${tab.title}`)
this.getList()
this.setState({
activeTab: decodeURIComponent(getParam('name'))
});
}
// 上下展示
pulldown = () => {
this.setState(status => ({
ispull: !status.ispull,
display: status.ispull ? 'none' : 'block'
}), () => {
this.state.ispull ? document.addEventListener('touchmove', stopScroll, {
passive: false
}) : document.removeEventListener('touchmove', stopScroll)
});
}
// 上下展示
pulldown = () => {
this.setState(status => ({
ispull: !status.ispull,
display: status.ispull ? 'none' : 'block'
}), () => {
this.state.ispull ? document.addEventListener('touchmove', stopScroll, {
passive: false
}) : document.removeEventListener('touchmove', stopScroll)
});
}
// 弹窗里面tab点击查询
labelclick = (item) => {
this.props.history.push(`/courselist?id=${item.c_id}&name=${item.c_name}`)
this.getList()
this.setState(status => ({
ispull: !status.ispull,
display: status.ispull ? 'none' : 'block',
activeTab: decodeURIComponent(getParam('name'))
}))
}
// 弹窗里面tab点击查询
labelclick = (item) => {
this.props.history.push(`/courselist?id=${item.c_id}&name=${item.c_name}`)
this.getList()
this.setState(status => ({
ispull: !status.ispull,
display: status.ispull ? 'none' : 'block',
activeTab: decodeURIComponent(getParam('name'))
}))
}
toCourseDetail = (id) => {
const {dispatch, history} = this.props;
// dispatch(getCourses(id, () => {
history.push(`/detail?id=${id}`)
// }));
}
toCourseDetail = (id) => {
const {dispatch, history} = this.props;
// dispatch(getCourses(id, () => {
history.push(`/detail?id=${id}`)
// }));
}
toClassify = () => {
this.props.history.replace('/classify');
}
toClassify = () => {
this.props.history.replace('/classify');
}
render() {
const {user = {}} = this.props;
let isLogin = user.data && user.data.uid ? true : false;
const bottom = (
<i className={'iconfont iconiconfront-69 pull-down'}></i>
)
const top = (
<i className={'iconfont iconiconfront-71 pull-down'}></i>
)
render() {
const {user = {}} = this.props;
let isLogin = user.data && user.data.uid ? true : false;
const bottom = (
<i className={'iconfont iconiconfront-69 pull-down'}></i>
)
const top = (
<i className={'iconfont iconiconfront-71 pull-down'}></i>
)
let page = this.state.allClass.findIndex((item) => item.title === this.state.activeTab)
return (
<div className='class-child'>
<HeaderSearch
isLogin={isLogin}
toHref={this.toClassify}
/>
<Loading isLoading={this.state.isLoading}>
<div className='class-content'>
{/* <WhiteSpace/> */}
<div onClick={this.pulldown.bind(this)}>
{this.state.ispull ? top : bottom}
</div>
<StickyContainer>
{/* <Tabs
let page = this.state.allClass.findIndex((item) => item.title === this.state.activeTab)
return (
<div className='class-child'>
<HeaderSearch
isLogin={isLogin}
toHref={this.toClassify}
/>
<Loading isLoading={this.state.isLoading}>
<div className='class-content'>
{/* <WhiteSpace/> */}
<div onClick={this.pulldown.bind(this)}>
{this.state.ispull ? top : bottom}
</div>
<StickyContainer>
{/* <Tabs
tabs={this.state.allClass}
animated={false}
page={page}
......@@ -172,113 +172,148 @@ class Classify extends Component {
<Tabs.DefaultTabBar {...props}/>
</div>}
> */}
<Tabs
tabs={this.state.allClass}
animated={false}
page={page}
onChange={(tab) => this.ontabclick(tab)}
renderTabBar={props => {
return (
<Sticky>
{({ style }) => {
return (
<div style={{ ...style, top: `${this.state.top}px`, zIndex: 1 }}>
<Tabs.DefaultTabBar {...props} />
</div>
)
}}
</Sticky>
)
}}
>
<div className='tabs'>
<ul>
{this.state.data && this.state.data.length > 0 && this.state.data.map((item, index) => {
const Info = (
<div className="info">
<p className='title'
onClick={() => this.toCourseDetail(item.course_id)}>
{item.course_title}
</p>
<p className='contact text-overflow-2'>{item.desc}</p>
<div className='des'>
{!item.is_buy && <p className="course-price">
<span className="new">¥{item.price1}</span>
<span className="old">¥{item.price0}</span>
</p>
}
{item.is_buy &&
<span className="isbuy">已购买</span>
}
</div>
</div>
)
const status = (
!item.is_buy &&
<div>
{item.bargain_num === 0 && item.groupon_num !== 0 &&
<p className='course-status'>拼团减{item.groupon_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>
)
return (
<VList
key={index}
status={status}
img={item.image_name}
id={item.course_id}
info={Info}
toDetail={this.toCourseDetail}
/>
)
})}
</ul>
</div>
</Tabs>
<Tabs
tabs={this.state.allClass}
animated={false}
page={page}
onChange={(tab) => this.ontabclick(tab)}
renderTabBar={props => {
return (
<Sticky>
{({style}) => {
return (
<div style={{...style, top: `${this.state.top}px`, zIndex: 1}}>
<Tabs.DefaultTabBar {...props} />
</div>
)
}}
</Sticky>
)
}}
>
<div className='tabs'>
<ul>
{this.state.data && this.state.data.length > 0 && this.state.data.map((item, index) => {
const Info = (
<div className="info">
<p className='title'
onClick={() => this.toCourseDetail(item.course_id)}>
{item.course_title}
</p>
<p className='contact text-overflow-2'>{item.desc}</p>
<div className='des'>
{
item.is_restricted ?
<LimitFree course={item}/>
: item.is_buy
? <span className="isbuy">已购买</span>
: <p className="course-price">
<span className="new">¥{item.price1}</span>
<span className="old">¥{item.price0}</span>
</p>
}
</div>
</div>
)
const status = (
!item.is_buy &&
<div>
{item.bargain_num === 0 && item.groupon_num !== 0 &&
<p className='course-status'>拼团减{item.groupon_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>
)
return (
<VList
key={index}
status={status}
img={item.image_name}
id={item.course_id}
info={Info}
toDetail={this.toCourseDetail}
/>
)
})}
</ul>
</div>
</Tabs>
</StickyContainer>
<WhiteSpace/>
</div>
<div className='mbc-box' style={{display: this.state.display}}>
{
this.state.arr.basics &&
<div className="tabcontent">
<ClassCourse activeTab={this.state.activeTab} data={this.state.arr.basics.list}
title={this.state.arr.basics.name} labelclick={this.labelclick}/>
<ClassCourse activeTab={this.state.activeTab} data={this.state.arr.advanced.list}
title={this.state.arr.advanced.name} labelclick={this.labelclick}/>
</div>
}
</div>
</Loading>
</div>
)
}
</StickyContainer>
<WhiteSpace/>
</div>
<div className='mbc-box' style={{display: this.state.display}}>
{
this.state.arr.basics &&
<div className="tabcontent">
<ClassCourse activeTab={this.state.activeTab} data={this.state.arr.basics.list}
title={this.state.arr.basics.name} labelclick={this.labelclick}/>
<ClassCourse activeTab={this.state.activeTab} data={this.state.arr.advanced.list}
title={this.state.arr.advanced.name} labelclick={this.labelclick}/>
</div>
}
</div>
</Loading>
</div>
)
}
}
function ClassCourse(props) {
return (
<div className="class-course">
<p className='course-items-title'>{props.title}</p>
<div className='items-box'>
{
props.data && props.data.length > 0 && props.data.map((item, index) => {
return (
<span className={props.activeTab === item.c_name ? 'active-label' : 'item-label'}
key={index} onClick={e => props.labelclick(item)}>{item.c_name}</span>
)
})
}
</div>
</div>
)
return (
<div className="class-course">
<p className='course-items-title'>{props.title}</p>
<div className='items-box'>
{
props.data && props.data.length > 0 && props.data.map((item, index) => {
return (
<span className={props.activeTab === item.c_name ? 'active-label' : 'item-label'}
key={index} onClick={e => props.labelclick(item)}>{item.c_name}</span>
)
})
}
</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;
html,body,#root {
html, body, #root {
height: 100%;
}
.class-child {
position: relative;
height: 100%;
.preferential{
.preferential {
width: 100%;
height: 44px;
position: fixed;
......@@ -20,7 +21,7 @@ html,body,#root {
// padding: 88px 12px 0;
position: relative;
.custom-render-bar{
.custom-render-bar {
position: fixed;
top: 43px;
left: 0;
......@@ -51,6 +52,7 @@ html,body,#root {
background-color: rgba(224, 46, 36, 0.6);
}
.return_cash {
position: absolute;
width: 31px;
......@@ -103,14 +105,23 @@ html,body,#root {
.isbuy {
display: inline-block;
width: 61px;
height: 18px;
background-color: $bg_active;
border-radius: 9px;
color: $white;
font-size: 12px;
color: #09f;
font-size: 15px;
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 {
display: flex;
margin-top: 10px;
margin-bottom: 50px;
ul {
width: 100%;
}
......@@ -136,6 +148,7 @@ html,body,#root {
background-color: $bg_fff;
color: $color_666;
}
.am-tabs-tab-bar-wrap {
padding-right: 20px;
}
......@@ -216,6 +229,7 @@ html,body,#root {
margin-bottom: -5px;
font-size: 12px;
}
.active-label {
display: inline-block;
width: 30.5%;
......@@ -234,8 +248,9 @@ html,body,#root {
}
}
}
.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';
import Mask from '@/common/Mask/index';
class BtnStatus extends Component {
constructor(props) {
super(props)
this.state = {
isbuy: 1,
is_baoming: 0,
group_status: 3,
in_cart: false,
countdown: 0,
barInfo: {},
bindPhone: false,
bindConfrm: false,
bindInfo: {}, // 冲突信息
formInfo: {},
}
constructor(props) {
super(props)
this.state = {
isbuy: 1,
is_baoming: 0,
group_status: 3,
in_cart: false,
countdown: 0,
barInfo: {},
bindPhone: false,
bindConfrm: false,
bindInfo: {}, // 冲突信息
formInfo: {},
}
componentDidMount() {
// this.getBargainInfo()
this.group = false;
}
componentDidMount() {
// 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();
}
// 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()
// }
// }
// if(nextProps.data && nextProps.data.is_bargain) {
// this.getBargainInfo()
// }
componentWillReceiveProps(nextProps) {
const { data = {}, user = {}} = nextProps;
if(data.is_bargain && user.data && user.data.uid) {
this.getBargainInfo();
this.setState({
courseInfo: data,
countdown: nextProps.countdown,
});
}
// // 加入购物车 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;
// 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);
}
})
}
};
// 普通课程的立即报名 要模拟结算过程
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')
};
// 普通课程的立即报名 要模拟结算过程
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 {
if (barInfo.bargain_status === 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);
}
})
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({
isShowOverlay: false,
bargainStatus: '',
isShowOverlay: true,
bargainStatus: 1,
})
}
}
// 砍价接口
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')
};
// 一键开团
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 {
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 {
Toast.info(msg, 2)
}
})
Toast.info(res.data.msg, 2);
}
})
}
};
// 开始学习
toStudy=(vCourseId,isHaveVideo)=>{
const { history } = this.props;
if(isHaveVideo == 0){
Toast.info('尚未开课,开课后立即上传课程~', 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 = () => {
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 {
history.push(`/play/video?id=${vCourseId}`)
Toast.info(msg, 2)
}
})
}
//获取砍价信息
getBargainInfo = () => {
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)
}
})
}
// 开始学习
toStudy = (vCourseId, isHaveVideo) => {
const {history} = this.props;
if (isHaveVideo == 0) {
Toast.info('尚未开课,开课后立即上传课程~', 2)
} else {
history.push(`/play/video?id=${vCourseId}`)
}
}
//获取砍价信息
getBargainInfo = () => {
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) => {
console.log(key);
this.setState({
[key]: false
});
}
}
<span className='btn btn-s bg-FD7700' onClick={e => this.simpleCourse()}>立即报名</span>
</div>
}
// 绑定手机号 -- 确认
confirmBindPhone = (params, bindInfo) => {
this.setState({
bindPhone: false,
bindConfrm: true,
formInfo: params,
bindInfo
});
}
{/* 定金课程 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>
}
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>
}
<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'>
{/*已购买*/}
{
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>{${info.pdd_group_info.price}`}</span>
<span>一键开团</span>
</span>
</button>
</div>
}
{/*拼团 已开团*/}
{
info.is_baoming === 0 && info.group_status === 4 &&
<div className='btns-box'>
<a className='consult consult-s' onClick={()=>this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<div className='btn btn-l bg-E02E24' onClick={this.props.invitedFriends}>
邀请好友参团 {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>
}
</button>
</div>
}
{/*拼团 已开团*/}
{
info.is_baoming === 0 && info.group_status === 4 &&
<div className='btns-box'>
<a className='consult consult-s' onClick={() => this.qimoChatClick()}>
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<div className='btn btn-l bg-E02E24' onClick={this.props.invitedFriends}>
邀请好友参团 {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>
}
{
/*
*
* 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) {
return (
<div className='cancel-bargain'>
<p className='top-img'><i className='iconfont icondanseshixintubiao-8'></i></p>
<p className='tip-mess'>您已发起砍价,直接购买将清除已砍金额。直接购买可使用优惠券~</p>
<div className="btns">
<button onClick={props.close}>取消</button>
<button onClick={props.cancel}>确定</button>
</div>
</div>
)
return (
<div className='cancel-bargain'>
<p className='top-img'><i className='iconfont icondanseshixintubiao-8'></i></p>
<p className='tip-mess'>您已发起砍价,直接购买将清除已砍金额。直接购买可使用优惠券~</p>
<div className="btns">
<button onClick={props.close}>取消</button>
<button onClick={props.cancel}>确定</button>
</div>
</div>
)
}
export default connect(
state => ({
user: state.user
}),
{getCourses}
state => ({
user: state.user
}),
{getCourses}
)(BtnStatus)
......@@ -7,7 +7,7 @@
background-color: $bg_fff;
display: flex;
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;
.consult {
......@@ -84,18 +84,26 @@
font-size: 12px;
}
}
.sign-up-now {
width: 50%;
color: #fff;
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 {
background-color: #0099FF;
font-size: 16px;
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 {
width: 50%;
}
......
import React, {Component} from 'react'
import React, { Component } from 'react'
import './index.scss'
import Bargain from './bargain'
import Group from './group'
import OutLine from './outline'
import {HeaderBar, CallApp} from '../../common'
import { HeaderBar, CallApp } from '../../common'
import ShareRank from "./shareRank"
import Audition from "./audition"
import Single from "./single"
......@@ -11,575 +11,613 @@ import SingleSuccess from './single/singleSuccess';
import BtnStatus from "./btnstatus"
import Barrage from './barrage'
import Deposit from './deposit'
import {connect} from "react-redux"
import {getCourses, addCourseToCart} from "./actions"
import {getParam, http, browser, wxShare} from "@/utils"
import {Toast} from 'antd-mobile'
import {bindActionCreators} from "redux";
import {delCountryNum} from './../country/countryRedux';
import { connect } from "react-redux"
import { getCourses, addCourseToCart } from "./actions"
import { getParam, http, browser, wxShare } from "@/utils"
import { Toast } from 'antd-mobile'
import { bindActionCreators } from "redux";
import { delCountryNum } from './../country/countryRedux';
import { Popup } from "@common/index"
import RedPacket from './redPacket';
import {Link} from "react-router-dom";
import ExpandActiveToast from "../Index/expandActiveToast";
class Detail extends Component {
courseId
constructor(props) {
super(props)
this.state = {
isbuy: 0,
isvip: 0,
auditionBox: false,
singleBox: false,
singleType: 1,
shareRank: false,
singMess: '',
barInfo: '',
share: false,
countdown: '00:00:00',
outList: [],
list: [],
course: {},
nowPrice: 0,
laterPrice: 0,
isPdd: 0, // 是否是拼团课程 控制首次单集购买后的 全集购买 接口: 拼团课程走拼团接口,否则直接走购买接口
isRedPacket: true,
countDownTime: '20s',
}
courseId
constructor(props) {
super(props)
this.state = {
isbuy: 0,
isvip: 0,
auditionBox: false,
singleBox: false,
singleType: 1,
shareRank: false,
singMess: '',
barInfo: '',
share: false,
countdown: '00:00:00',
outList: [],
list: [],
course: {},
nowPrice: 0,
laterPrice: 0,
isPdd: 0, // 是否是拼团课程 控制首次单集购买后的 全集购买 接口: 拼团课程走拼团接口,否则直接走购买接口
isRedPacket: true,
countDownTime: '20s',
}
}
componentDidMount() {
this.fetchCourseInfo();
const {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.judgeIsRedPacket();
componentDidMount() {
this.fetchCourseInfo();
const {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()
}
// 红包链接进入详情也
if (getParam('share_code')) {
this.setState({
isRedPacket: true
});
}
this.judgeIsRedPacket();
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;
if(code === 200) {
let currentCourseId = getParam('id');
if(today_browsed_courses.includes(Number(currentCourseId))) {
this.setState({
countDownTime: '任务完成'
});
}else{
this.startActivity();
}
}
}
getBorwerCourse = () => {
http.get(`${API.home}/sys/user/blessing`, {type: 4, course_id: getParam('id')}).then(res => {
let {code, data: {today_browsed_courses}} = res.data;
if (code === 200) {
let currentCourseId = getParam('id');
if (today_browsed_courses.includes(Number(currentCourseId))) {
this.setState({
countDownTime: '任务完成'
});
} else {
this.startActivity();
}
}
})
}
startActivity = () => {
let _this = this;
let countDownInterval = setInterval(function () {
let countDown = parseInt(_this.state.countDownTime);
countDown--;
if (countDown > 0) {
_this.setState({
countDownTime: countDown + 's'
});
} else if (countDown === 0) {
clearInterval(countDownInterval);
countDownInterval = null;
http.post(`${API.home}/sys/add/blessing`, {type: 4, course_id: getParam('id')}).then(res => {
let {code} = res.data;
if (code === 200) {
_this.setState({
countDownTime: '任务完成'
});
}
})
}
}
}, 1000)
}
// 判断时候未红包课程
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 = () => {
let _this = this;
let countDownInterval = setInterval(function() {
let countDown = parseInt(_this.state.countDownTime);
countDown--;
if(countDown > 0) {
componentDidUpdate(prevProps) {
if (prevProps.user.hasError !== this.props.user.hasError) {
this.fetchCourseInfo()
}
}
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({
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: '任务完成'
});
}
singleType: 6,
})
}
}, 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
});
}
} 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)
}
componentDidUpdate(prevProps) {
if (prevProps.user.hasError !== this.props.user.hasError) {
this.fetchCourseInfo()
}
}
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) => {
};
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,
})
// 正常购买单集成功
_this.setState({
singleType: 6,
})
} else if (Number(res.data.data.errno) === 201) {
// 0元参团
_this.setState({
singleType: 4,
})
// 0元参团
_this.setState({
singleType: 4,
})
} else if (Number(res.data.data.errno) === 202) {
// 0元购
_this.setState({
singleType: 3,
})
// 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,
})
// 三天内特价
_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)
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 (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)
}
})
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) => {
}
// 判断支付是否成功
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({
singMess: JSON.parse(window.localStorage.getItem('singMess'))
singleType: 6
})
http.get(`${API['base-api']}/class_order_status/${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 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)
}
})
} 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) => {
// Toast.info(singleType, 2);
const _this = this;
if (singleType === 2) {
_this.setState({
singleType,
nowPrice,
laterPrice
})
} else {
_this.setState({
singleType,
})
};
fetchCourseInfo = () => {
const id = getParam('id');
http.get(`${API.home}/m/course/detail/${id}`).then((res) => {
const {data, code} = res.data;
if (code === 200) {
if (data['redirect_url'] !== '') {
window.location.href = data['redirect_url']
}
};
fetchCourseInfo = () => {
const id = getParam('id');
http.get(`${API.home}/m/course/detail/${id}`).then((res) => {
const {data, code} = res.data;
if (code === 200) {
if(data['redirect_url'] !== ''){
window.location.href = data['redirect_url']
}
this.setState({
course: data
});
if (data.course_info) {
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({
course: data
countdown: `${hours}:${minutes}:${seconds}`
});
if (data.course_info) {
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
});
}
}, 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
});
}
// 点击子组件试听按钮
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 {
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 {
Toast.info(res.data.msg, 2);
}
})
// this.setState({
// auditionBox: true,
// })
Toast.info(res.data.msg, 2);
}
})
// this.setState({
// auditionBox: true,
// })
}
// 点击子组件单集购买按钮
toSingleset = (item) => {
const {user} = this.props
const uid = user && user.data && user.data.uid
if (!uid) {
this.props.history.push('/passport/login')
} else {
this.setState({
singleBox: true,
singleType: 1,
singMess: item
});
window.localStorage.setItem('singMess', JSON.stringify(item))
}
}
// 点击子组件单集购买按钮
toSingleset = (item) => {
const {user} = this.props
const uid = user && user.data && user.data.uid
if (!uid) {
this.props.history.push('/passport/login')
} else {
this.setState({
singleBox: true,
singleType: 1,
singMess: item
});
window.localStorage.setItem('singMess', JSON.stringify(item))
}
}
// componentWillReceiveProps(nextProps) {
// let _this = this;
// if (nextProps.courseInfo.course_info) {
// let courseInfo = nextProps.courseInfo.course_info;
// if (courseInfo.group_status === 3 || courseInfo.group_status === 4) {
// 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);
}
})
// 加入购物车 type:1 加入购物车,2加入购物车并跳转到购物车页面去支付
toCart = (type) => {
const {history, addCourseToCart} = this.props;
let data = {
course_id: getParam('id')
};
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}`);
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);
}
})
};
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
boxHide = (val) => {
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 = '/'
} else {
Toast.info(msg, 2, null, false)
}
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;
{/*弹幕*/}
<Barrage isShow={course_info.is_show}/>
const {d, h, m} = this.formatTime(course_info.limit_free_time)
{/*课程*/}
<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 &&
<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>
}
</div>
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')}`}/>
{/*弹幕*/}
<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>
: null
: null
}
</div>
</div>
</div>
{/*正常课程已购买时显示*/}
{/*正常课程已购买时显示*/}
{/*
{/*
没有权限:不显示
vip及赠课:显示黄的
不在vip范围内,单独购买:显示蓝的
......@@ -589,214 +627,214 @@ class Detail extends Component {
is_pay 1是单独购买 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 &&
<div className='group'>
上课QQ群:{course_info.course_qq},加群请备注您的学号:{course_info.uid}
</div>
}
{
course_info.is_baoming === 1 && course_info.is_pay == 1 && course_info.contact_type == 2 && course_info.course_qq &&
<div className='group'>
请添加班主任微信:{course_info.course_qq},添加时备注学号:{course_info.uid}
</div>
}
{
!(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'>
上课QQ群:{course_info.course_qq},加群请备注您的学号:{course_info.uid}
</div>
}
{
!(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'>
请添加班主任微信:{course_info.course_qq},添加时备注学号:{course_info.uid}
</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'>
<label>服务承诺</label>
<p>
{
course_info.service && course_info.service.length > 0 && course_info.service.map((item, index) => {
return (
<span key={index}> {item} </span>
)
})
}
</p>
</div>
{/*试听弹窗*/}
<Audition auditionBox={this.state.auditionBox} boxHide={this.boxHide}/>
{/*单集购买弹窗*/}
{
singleBox &&
<Single
singleType={this.state.singleType}
singleBox={this.state.singleBox}
boxHide={this.boxHide}
data={this.state.singMess}
vcourseId={course_info.v_course_id}
videoId={this.state.singMess.video_id}
title={course_info.course_title}
check={this.check}
courseId={course_info.course_id}
/>
}
{/* 单集购买成功弹窗 */}
{
singleType !== 1 &&
<SingleSuccess
boxHide={this.boxHide}
data={this.state.singMess}
singleType={singleType}
vcourseId={course_info.v_course_id}
videoId={this.state.singMess.video_id}
nowPrice={this.state.nowPrice}
isPdd={this.state.isPdd}
laterPrice={this.state.laterPrice}
courseId={course_info.course_id}
/>
}
{/*payCallback={this.payCallback}*/}
{/*weixinPay = {this.weixinPay}*/}
{/* 红包 */}
{
isRedPacket &&
<RedPacket
history={this.props.history}
country={this.props.country}
delCountryNum={this.props.delCountryNum}
userInfo={this.props.user.data}
/>
}
{/*分享赚钱*/}
{
course_info.is_dist &&
<ShareRank courseInfo={course_info}/>
}
{/**
* 拼团
* is_aist: 是否AI特训营
* group_status: 团状态,3:课程有小团 用户没参加小团;4:用户参加了小团
* 拼团价格为1分钱时,不允许参团
*/
}
{/*双十一期间不需要显示 不要删除*/}
{
isCent && !course_info.is_aist && (course_info.group_status === 3 || course_info.group_status === 4) &&
<Group
courseInfo={course_info}
history={this.props.history}
countdown={countdown}
invitedFriends={this.invitedFriends}
/>
}
{/*
{/*服务承诺*/}
<div className='promise'>
<label>服务承诺</label>
<p>
{
course_info.service && course_info.service.length > 0 && course_info.service.map((item, index) => {
return (
<span key={index}> {item} </span>
)
})
}
</p>
</div>
{/*试听弹窗*/}
<Audition auditionBox={this.state.auditionBox} boxHide={this.boxHide}/>
{/*单集购买弹窗*/}
{
singleBox &&
<Single
singleType={this.state.singleType}
singleBox={this.state.singleBox}
boxHide={this.boxHide}
data={this.state.singMess}
vcourseId={course_info.v_course_id}
videoId={this.state.singMess.video_id}
title={course_info.course_title}
check={this.check}
courseId={course_info.course_id}
/>
}
{/* 单集购买成功弹窗 */}
{
singleType !== 1 &&
<SingleSuccess
boxHide={this.boxHide}
data={this.state.singMess}
singleType={singleType}
vcourseId={course_info.v_course_id}
videoId={this.state.singMess.video_id}
nowPrice={this.state.nowPrice}
isPdd={this.state.isPdd}
laterPrice={this.state.laterPrice}
courseId={course_info.course_id}
/>
}
{/*payCallback={this.payCallback}*/}
{/*weixinPay = {this.weixinPay}*/}
{/* 红包 */}
{
isRedPacket &&
<RedPacket
history={this.props.history}
country={this.props.country}
delCountryNum={this.props.delCountryNum}
userInfo={this.props.user.data}
/>
}
{/*分享赚钱*/}
{
course_info.is_dist &&
<ShareRank courseInfo={course_info}/>
}
{/**
* 拼团
* is_aist: 是否AI特训营
* group_status: 团状态,3:课程有小团 用户没参加小团;4:用户参加了小团
* 拼团价格为1分钱时,不允许参团
*/
}
{/*双十一期间不需要显示 不要删除*/}
{
isCent && !course_info.is_aist && (course_info.group_status === 3 || course_info.group_status === 4) &&
<Group
courseInfo={course_info}
history={this.props.history}
countdown={countdown}
invitedFriends={this.invitedFriends}
/>
}
{/*
* 砍价
* is_baoming 否报名 0-未购买弹出报名 1-已购买弹出开始学习
* is_dist 是否分销课程
* is_bargain 是否砍价课程
*/}
{
course_info.is_baoming === 0 && (!course_info.is_aist) && course_info.is_bargain &&
<Bargain
country={this.props.country}
delCountryNum={this.props.delCountryNum}
/>
}
{/*课程介绍、大纲*/}
<OutLine
data={course_info}
toAudition={this.toAudition}
toSingleset={this.toSingleset}
/>
{/*课程按钮*/}
{
course_info &&
<BtnStatus
country={this.props.country}
countdown={countdown}
data={course_info}
user={this.props.user}
invitedFriends={this.invitedFriends}
// addCourseToCart={this.props.addCourseToCart}
toCart={this.toCart}
history={this.props.history}
/>
}
{
share ? (
<div
className='groupSuccessMbc'
onClick={() => {
this.setState({share: false})
}}
>
<div className='tipContent'>
{`还差${number}人,分享到3个群,成团率高达98%`}
</div>
<div className='tipArrow'>
<i className='iconfont iconyindao'/>
</div>
</div>
) : null
}
{
course_info.is_baoming === 0 && (!course_info.is_aist) && course_info.is_bargain &&
<Bargain
country={this.props.country}
delCountryNum={this.props.delCountryNum}
/>
}
{/*课程介绍、大纲*/}
<OutLine
data={course_info}
toAudition={this.toAudition}
toSingleset={this.toSingleset}
/>
{/*课程按钮*/}
{
course_info &&
<BtnStatus
country={this.props.country}
countdown={countdown}
data={course_info}
user={this.props.user}
invitedFriends={this.invitedFriends}
getCourse={this.getCourse}
// addCourseToCart={this.props.addCourseToCart}
toCart={this.toCart}
history={this.props.history}
/>
}
{
share ? (
<div
className='groupSuccessMbc'
onClick={() => {
this.setState({share: false})
}}
>
<div className='tipContent'>
{`还差${number}人,分享到3个群,成团率高达98%`}
</div>
</div>
)
}
<div className='tipArrow'>
<i className='iconfont iconyindao'/>
</div>
</div>
) : null
}
</div>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
// courseInfo: state.courseInfo,
user: {
...state.user
},
country: state.country
}
return {
// courseInfo: state.courseInfo,
user: {
...state.user
},
country: state.country
}
}
// const mapDispatchToProps = {
// fetchCoursesListIfNeeded
// }
const mapDispatchToProps = (dispatch) => {
return bindActionCreators(
{
getCourses,
addCourseToCart,
delCountryNum
},
dispatch
)
return bindActionCreators(
{
getCourses,
addCourseToCart,
delCountryNum
},
dispatch
)
}
......
......@@ -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 {
display: inline-block;
width: 66px;
......@@ -253,4 +269,51 @@
bottom: 4px;
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 {HeaderBar, VList} from '../../common'
import { http } from "@/utils";
import {Link} from 'react-router-dom'
import {Toast} from 'antd-mobile'
import {connect} from "react-redux"
import {getCourses} from './../detail/actions';
import { HeaderBar, VList } from '../../common'
import { http, dateCountDown } from "@/utils";
import { Link } from 'react-router-dom'
import { Toast } from 'antd-mobile'
import { connect } from "react-redux"
import Loading from '@/common/Loading'
class Purchased extends Component {
constructor(props) {
super(props)
this.state = {
data: [],
isLoading: true
}
constructor(props) {
super(props)
this.state = {
data: [],
isLoading: true
}
}
componentDidMount() {
this.getList()
}
componentDidMount() {
this.getList()
}
// 获取订单
getList = () => {
http.get(`${API.home}/m/my/courses`,).then((res) => {
if (res.data.code === 200) {
this.setState({
data: res.data.data,
isLoading: false
})
} else {
Toast.info(res.data.msg, 2);
}
// 获取订单
getList = () => {
http.get(`${API.home}/m/my/courses`,).then((res) => {
if (res.data.code === 200) {
this.setState({
data: res.data.data,
isLoading: false
})
}
toCourseDetail = (id) => {
const { dispatch, history } = this.props;
// dispatch(getCourses(id, () => {
history.push(`/detail?id=${id}`)
// }));
}
} else {
Toast.info(res.data.msg, 2);
}
})
}
render() {
const {user} = this.props
const uid = user && user.data && user.data.uid
return (
<div className='purchased-box'>
<HeaderBar arrow={true} title='已购课程' cart={false} toHref='/my' />
<Loading isLoading={this.state.isLoading}>
{
this.state.data && this.state.data.length > 0 ?
<div className="purchased-body">
<div className='tip'>加群请备注您的学号:{uid}</div>
{
this.state.data.map((item, index) => {
const Info = (
<div className="info">
<p className='title' onClick={() => this.toCourseDetail(item.course_id)}>
{/* <Link to={`/detail?id=${item.course_id}`}> */}
{item.course_title}
{/* </Link> */}
</p>
<p className='contact text-overflow-2'>{item.simpledescription}</p>
toCourseDetail = (id) => {
const {dispatch, history} = this.props;
// dispatch(getCourses(id, () => {
history.push(`/detail?id=${id}`)
// }));
}
render() {
const {user} = this.props
const uid = user && user.data && user.data.uid
return (
<div className='purchased-box'>
<HeaderBar arrow={true} title='已购课程' cart={false} toHref='/my'/>
<Loading isLoading={this.state.isLoading}>
{
this.state.data && this.state.data.length > 0 ?
<div className="purchased-body">
<div className='tip'>加群请备注您的学号:{uid}</div>
{
this.state.data.map((item, index) => {
const Info = (
<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 &&
<div className='des'>助教微信:{item.assist_weixin}</div>
}
{
!item.is_aist && item.contact_type == 1 && item.course_qq &&
<div className='des'>QQ群:{item.course_qq}</div>
}
{
!item.is_aist && item.contact_type == 2 && item.course_qq &&
<div className='des'>班主任微信:{item.course_qq}</div>
}
</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
key={index}
img={item.image_name}
id={item.course_id}
info={Info}
status={status}
courseExpire={courseExpire}
toDetail={this.toCourseDetail}
/>
)
})
}
</div>
: <div className="cart-tip">
<p className='cart-mess'>您还没有课程哦,快去逛逛吧~</p>
<Link to='/classify'>去逛逛</Link>
</div>
}
</Loading>
{
item.is_aist &&
<div className='des'>助教微信:{item.assist_weixin}</div>
}
{
!item.is_aist && item.contact_type == 1 && item.course_qq &&
<div className='des'>QQ群:{item.course_qq}</div>
}
{
!item.is_aist && item.contact_type == 2 && item.course_qq &&
<div className='des'>班主任微信:{item.course_qq}</div>
}
</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
key={index}
img={item.image_name}
id={item.course_id}
info={Info}
status={status}
courseExpire={courseExpire}
toDetail={this.toCourseDetail}
/>
)
})
}
</div>
: <div className="cart-tip">
<p className='cart-mess'>您还没有课程哦,快去逛逛吧~</p>
<Link to='/classify'>去逛逛</Link>
</div>
}
</Loading>
</div>
)
}
</div>
)
}
}
export default connect(
state => ({user: state.user}),
null
state => ({user: state.user}),
null
)(Purchased)
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 {
background-color: $bg_fff;
.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 {
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 {
background-color: #fff;
.content {
padding-bottom: 10px;
border-bottom: 1px solid #e7eaf1;
.cover {
flex: inherit;
width: 42.2%;
.info {
width: 52.3%;
position: relative;
display: block;
img {
width: 100%;
}
}
}
.title {
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 {
width: 52.3%;
position: relative;
display: block;
.title {
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;
}
.des {
position: absolute;
bottom: 5px;
color: $active;
font-size: 14px;
height: 14px;
line-height: 14px;
}
}
.des {
position: absolute;
bottom: 5px;
color: $active;
font-size: 14px;
height: 14px;
line-height: 14px;
}
}
}
.cart-tip {
color: #555;
margin-top: 140px;
text-align: center;
.iconfridge {
font-size: 21px;
}
.cart-mess {
font-size: 12px;
color: $color_666;
}
.cart-tip {
color: #555;
margin-top: 140px;
text-align: center;
a {
display: inline-block;
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;
}
.iconfridge {
font-size: 21px;
}
.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);
.cart-mess {
font-size: 12px;
color: $color_666;
}
.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;
a {
display: inline-block;
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 {
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";
function getStudyTime(seconds) {
return {
hour: Math.floor(seconds / (60 * 60)),
min: Math.floor(seconds / 60) % 60,
sec: seconds % 60
}
return {
hour: Math.floor(seconds / (60 * 60)),
min: Math.floor(seconds / 60) % 60,
sec: seconds % 60
}
}
const AddCourse = React.memo(({addCourseClick}) => (
<div className='add-course'>
<button className='add' onClick={addCourseClick}>添加课程+</button>
</div>
<div className='add-course'>
<button className='add' onClick={addCourseClick}>添加课程+</button>
</div>
))
function Record({record: {seconds, lesson_name}}) {
let re = /第[\s\S]+?课/,
result = ''
let re = /第[\s\S]+?课/,
result = ''
if (lesson_name) {
let matchResult = re.exec(lesson_name)
result += (matchResult && matchResult[0]) ? matchResult[0] : ''
}
if (lesson_name) {
let matchResult = re.exec(lesson_name)
result += (matchResult && matchResult[0]) ? matchResult[0] : ''
}
if (seconds) {
let studyTime = getStudyTime(seconds)
let hour = studyTime.hour ? String(studyTime.hour).padStart(2, '0') + ':' : '',
min = studyTime.min ? String(studyTime.min).padStart(2, '0') + ':' : '',
sec = studyTime.sec ? String(studyTime.sec).padStart(2, '0') : ''
if (seconds) {
let studyTime = getStudyTime(seconds)
let hour = studyTime.hour ? String(studyTime.hour).padStart(2, '0') + ':' : '',
min = studyTime.min ? String(studyTime.min).padStart(2, '0') + ':' : '',
sec = studyTime.sec ? String(studyTime.sec).padStart(2, '0') : ''
result += hour + min + sec
}
result += hour + min + sec
}
return (
<span className={'record'}>
return (
<span className={'record'}>
{
result.length ? `学习到${result}` : null
result.length ? `学习到${result}` : null
}
</span>
)
)
}
const Bottom = React.memo(({item}) => {
if (item.ago || item.seconds) {
let date = new Date(item.ago * 1000)
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>
)
}
if (item.ago || item.seconds) {
let date = new Date(item.ago * 1000)
let time = isToday(date) ? format(date, 'HH时mm分') : format(date, 'MM月DD日')
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 {
list
list
state = {
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')
}
state = {
isLoading: true
}
componentDidMount() {
this.props.switchTab(false)
this.props.fetchCoursesListIfNeeded()
handleClick = (id, item) => {
const {history} = this.props
const {mode, course_id} = item
if (mode && mode == 6) {
history.push(`/python?id=${course_id}`)
return
}
componentWillUnmount() {
this.props.switchTab(true);
history.push(`/play/video?id=${id}`)
}
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 ?
<AddCourse addCourseClick={this.addCourseClick}/>
: null
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>
}
</>
:
<div className="empty">
<p><i className='iconfont iconfish'/></p>
<p className='empty-prompt'>您还没有课程哦,赶快去选课吧~</p>
<p>
<Link className='select-course' to='/classify'>去选课</Link>
</p>
</div>
<Bottom item={item}/>
</div>
)
const status = (
item.is_aist
? <span className='status'>返现</span>
: item.course_expire
? <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(
state => ({
courseList: state.myCourses.courseList,
user: state.user,
isLoading: state.myCourses.isLoading
}),
{
fetchCoursesListIfNeeded,
switchTab
})(MyCourses)
state => ({
courseList: state.myCourses.courseList,
user: state.user,
isLoading: state.myCourses.isLoading
}),
{
fetchCoursesListIfNeeded,
switchTab
})(MyCourses)
import React, { Component } from 'react'
import HeaderBar from '@/common/HeaderBar'
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 Recommendation from './recommendation'
import VideoCatalog from './video-catalog'
......@@ -21,862 +21,958 @@ import './CustomPlayButton'
let alert = Modal.alert
function ProgressShareModal(props) {
return (
props.isShow &&
<div className='progress-share-modal-wrapper'>
<div className="progress-share-modal">
<div className="title">每日打卡</div>
<ul className="progress-container">
<li>
<div className="title">累计学习</div>
<div className="number"><span className='num'>{props.data.learn_day_count}</span>天</div>
</li>
<li>
<div className="title">行动力超过</div>
<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}/>
return (
props.isShow &&
<div className='progress-share-modal-wrapper'>
<div className="progress-share-modal">
<div className="title">每日打卡</div>
<ul className="progress-container">
<li>
<div className="title">累计学习</div>
<div className="number"><span className='num'>{props.data.learn_day_count}</span>天</div>
</li>
<li>
<div className="title">行动力超过</div>
<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>
)
}
class Video extends Component {
video //video element
player //video player instance
courseID
ws //websocket instance
timer
token
count
watchSec
previousPlaybackRate = 1
currentPlaybackRate = 1
reconnect = true
// timeEnough = false
recordSocket
recordTimer
isCurrentVideoFirstPlay = true
RECENTLEARN = "recent_learn"
state = {
title: '',
courseId: null,
videoList: [],
datum: [],
currentVideoSrc: '',
activeIndex: 0,
isAuth: true,
course: {}, // course.course_id 为 0 或 '' 时 为免费课程
salePrice: null,
vCourseId: null,
isLoading: true,
isShowShareModal: false,
shareData: {},
singleBox: false,
singMess: '',
singleType: 1,// 单集购买需要
nowPrice: 0,// 单集购买需要
laterPrice: 0,// 单集购买需要
video //video element
player //video player instance
courseID
ws //websocket instance
timer
token
count
watchSec
previousPlaybackRate = 1
currentPlaybackRate = 1
reconnect = true
// timeEnough = false
recordSocket
recordTimer
isCurrentVideoFirstPlay = true
RECENTLEARN = "recent_learn"
state = {
title: '',
courseId: null,
videoList: [],
datum: [],
currentVideoSrc: '',
activeIndex: 0,
isAuth: true,
course: {}, // course.course_id 为 0 或 '' 时 为免费课程
salePrice: null,
vCourseId: null,
isLoading: true,
isShowShareModal: false,
shareData: {},
singleBox: false,
singMess: '',
singleType: 1,// 单集购买需要
nowPrice: 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
}
componentDidMount() {
if (window.location.protocol === 'https:') {
window.location.replace('http' + window.location.href.slice(5))
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.courseID = getParam('id')
if (!this.courseID) {
this.props.history.replace('/')
return
}
// 直接购买
tobuy = () => {
// 详情页单集购买到该页面,url中的id不是课程id
const {course = {}} = this.state;
http.get(`${API['base-api']}/m/cart/addtopreorder/[${course.course_id}]`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push(`/order?id=${course.course_id}`, {simple: 1})
} else {
Toast.info(res.data.msg, 2);
}
})
this.setState({
courseId: this.courseID
})
const {location, location: {state = {}}} = this.props;
if (state.oid) {
this.check(state.oid);
}
// 购买单集
toSingleset = (item) => {
// console.log(item);
this.setState({
singleBox: true,
singleType: 1,
singMess: item
})
window.localStorage.setItem('singMess', JSON.stringify(item))
if (getParam('is_class') === 1 || getParam('weixinpay')) {
this.payCallback()
}
// 自组件传给父组件的boxHide
boxHide = (val) => {
this.setState({singleBox: val, singleType: 1})
if (browser.isWeixin) {
this.isweixinPay()
}
// 单集购买 H5支付成功后回调
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({
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)
}
};
// 单集购买 微信内支付成功后回调
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.token = jsCookie.get('token')
this.getVideoList()
this.getDatumCatalog()
}
// 直接购买
tobuy = () => {
// 详情页单集购买到该页面,url中的id不是课程id
const {course = {}} = this.state;
http.get(`${API['base-api']}/m/cart/addtopreorder/[${course.course_id}]`).then((res) => {
if (res.data.errno === 0) {
this.props.history.push(`/order?id=${course.course_id}`, {simple: 1})
} else {
Toast.info(res.data.msg, 2);
}
})
}
// 购买单集
toSingleset = (item) => {
this.setState({
singleBox: true,
singleType: 1,
singMess: item
})
window.localStorage.setItem('singMess', JSON.stringify(item))
}
// 自组件传给父组件的boxHide
boxHide = (val) => {
this.setState({singleBox: val, singleType: 1})
}
// 单集购买 H5支付成功后回调
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({
singleType: 6,
_this.setState({
singleType: 6,
})
} else if (Number(res.data.data.errno) === 201) {
} else if (Number(res.data.data.errno) === 201) {
// 0元参团
this.setState({
singleType: 4,
_this.setState({
singleType: 4,
})
} else if (Number(res.data.data.errno) === 202) {
} else if (Number(res.data.data.errno) === 202) {
// 0元购
this.setState({
singleType: 3,
_this.setState({
singleType: 3,
})
} else if (Number(res.data.data.errno) === 203) {
} 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,
_this.setState({
nowPrice: res.data.data.data.now_price,
laterPrice: res.data.data.data.three_day_later_price,
singleType: 2,
})
} else {
} else {
Toast.info(res.data.data.msg, 2)
}
}
})
}
})
}, 1000)
}
// 9502 初始化 监听事件
setupWS = () => {
this.ws = new WebSocket(API["process-api"]);
this.ws.addEventListener('error', () => {
this.ws = null
})
this.ws.addEventListener('close', () => {
if (this.reconnect) {
this.ws = null
setTimeout(() => {
this.setupWS();
}, 1000)
}
clearInterval(this.timer)
this.timer = null;
};
// 单集购买 微信内支付成功后回调
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.ws.addEventListener('message', e => {
const data = JSON.parse(e.data);
data.code == 4040 && (this.reconnect = false);
if(data.code === 0) {
console.log("上次的学习记录" + JSON.stringify(data));
if(data.data && data.data.position) {
this.player.currentTime(data.data.position);
// 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('支付失败')
}
}
)
}
})
}
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);
}
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({
singleType: 6,
//视频结束请求接口
getShareProgressInfo = () => {
http.get(`${API['base-api']}/m/aist/share_data/${this.courseID}/${this.state.videoList[this.state.activeIndex]['id']}`)
.then(res => {
const {data} = res
if (data.errno == 200) {
this.setState({shareData: data.data, isShowShareModal: true})
}
})
}
})
} else if (Number(res.data.data.errno) === 201) {
// 0元参团
this.setState({
singleType: 4,
//告诉服务端计算进度
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
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++
}
}
})
} else {
Toast.info(res.data.data.msg, 2)
}
})
}
// 9502 初始化 监听事件
setupWS = () => {
this.ws = new WebSocket(API["process-api"]);
this.ws.addEventListener('error', () => {
this.ws = null
})
this.ws.addEventListener('close', () => {
if (this.reconnect) {
this.ws = null
setTimeout(() => {
this.setupWS();
}, 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;
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.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;
})
}
//视频结束请求接口
getShareProgressInfo = () => {
http.get(`${API['base-api']}/m/aist/share_data/${this.courseID}/${this.state.videoList[this.state.activeIndex]['id']}`)
.then(res => {
const {data} = res
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 === '') {
return;
}
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
})
let ctype = 0;
if (course.is_aist) {
ctype = 2;
}
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
// 计算进度 根据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,
})
}
// 发送时间消息
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;
}
// 选择新的视频
selectVideo = index => {
if (index === this.state.activeIndex) {
return
let ctype = 0;
if (course.is_aist) {
ctype = 2;
}
// 时间足够不发送
// 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; // 切换视频则重置这个变量 因为新视频肯定是首次播放
this.sendWatchTime(this.watchSec, this.currentPlaybackRate)
this.countSchedule(); // 计算进度 -- 选择新视频(可能是M端特有的)
}
}, 1000)
}
// 初始化视频播放器
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.setState(
{
activeIndex: index
},
() => {
if (this.hasAuth(this.state.activeIndex)) {
this.setPlayerSrc(this.state.videoList[index]['play_url'])
this.sendLastRecord()
this.playVideo()
} else {
this.getCoursePrice();
}
}
);
}
getLastVideoIndex = lastIndex => {
return this.state.videoList.findIndex(item => item.id == lastIndex)
}
})
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;
if (this.state.limitFreePopup.is_free) {
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
}
getVideoList = () => {
let url = '';
if (getParam('video_id')) {
url = `${API.home}/m/course/play/${this.courseID + '?video_id=' + getParam('video_id')}`
http.post(`${API['base-api']}/sys/get_class_audition`, {
video_id: getParam('video_id')
})
this.isCurrentVideoFirstPlay = true; // 切换视频则重置这个变量 因为新视频肯定是首次播放
this.sendWatchTime(this.watchSec, this.currentPlaybackRate)
this.countSchedule(); // 计算进度 -- 选择新视频(可能是M端特有的)
this.setupTimer();
this.setState(
{
activeIndex: index
},
() => {
if (this.hasAuth(this.state.activeIndex)) {
this.setPlayerSrc(this.state.videoList[index]['play_url'])
this.sendLastRecord()
this.playVideo()
} 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 => ({
videoList: data['lessons'],
currentVideoSrc: data['lessons'][state.activeIndex]['play_url'],
course: data.course,
courseId: data.course['course_id'],
vCourseId: data.course['v_course_id'],
title: data.course['course_title'],
isLoading: false
}),
this.playSetup
)
} else {
Toast.info(data.msg)
}
}
)
}
);
}
getLastVideoIndex = lastIndex => {
return this.state.videoList.findIndex(item => item.id == lastIndex)
}
getVideoList = () => {
let url = '';
if (getParam('video_id')) {
url = `${API.home}/m/course/play/${this.courseID + '?video_id=' + getParam('video_id')}`
http.post(`${API['base-api']}/sys/get_class_audition`, {
video_id: getParam('video_id')
})
} else {
url = `${API.home}/m/course/play/${this.courseID}`
}
playSetup = () => {
// is_aist,是否AI特训营
const {course = {}} = this.state;
// if (Number(course.course_id) === 0 || course.course_id === '') {
// console.log('免费课程 拦截');
// }else{
let _this = this;
this.setupWS();
this.setupTimer();
let scheduleTime = setTimeout(function () {
clearTimeout(scheduleTime);
scheduleTime = null;
_this.countSchedule(); // 刚进入页面的时候 就计算进度 先获取视频列表getVideoList 获取列表后 播放选择的视频 然后计算进度
}, 1000);
// }
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('/')
}
}])
}
http.get(url).then(res => {
const {data = {}, code} = res.data;
if (code === 200) {
this.setState(
state => ({
videoList: data['lessons'],
currentVideoSrc: data['lessons'][state.activeIndex]['play_url'],
course: data.course,
courseId: data.course['course_id'],
vCourseId: data.course['v_course_id'],
title: data.course['course_title'],
isLoading: false
}),
this.playSetup
)
this.getLimitFreePopup(data.course.course_id)
} else {
Toast.info(data.msg)
}
}
)
}
playSetup = () => {
// is_aist,是否AI特训营
const {course = {}} = this.state;
// if (Number(course.course_id) === 0 || course.course_id === '') {
// }else{
let _this = this;
this.setupWS();
this.setupTimer();
let scheduleTime = setTimeout(function () {
clearTimeout(scheduleTime);
scheduleTime = null;
_this.countSchedule(); // 刚进入页面的时候 就计算进度 先获取视频列表getVideoList 获取列表后 播放选择的视频 然后计算进度
}, 1000);
// }
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 => {
if (!this.player) {
this.initializePlayer()
}
this.player.src({
src,
type: 'application/x-mpegURL'
})
setPlayerSrc = src => {
if (!this.player) {
this.initializePlayer()
}
this.player.src({
src,
type: 'application/x-mpegURL'
})
}
playVideo = () => {
this.player.ready(() => {
this.player.play()
})
playVideo = () => {
this.player.ready(() => {
this.player.play()
})
}
}
getDatumCatalog() {
http.get(`${API.home}/m/course/data/${this.courseID}`)
.then(res => {
const data = res.data
if (data.code === 200) {
getDatumCatalog() {
http.get(`${API.home}/m/course/data/${this.courseID}`)
.then(res => {
const data = res.data
if (data.code === 200) {
this.setState({
datum: data.data
})
this.setState({
datum: data.data
})
} else {
Toast.info(data.msg)
}
})
}
} else {
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 => {
return this.state.videoList[index]['video_size'] !== 0
}
playWithAuth = () => {
const {videoList, activeIndex} = this.state
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']
})
}
})
if (this.hasAuth(activeIndex)) {
this.setPlayerSrc(videoList[activeIndex]['play_url'])
}
}
playWithAuth = () => {
const {videoList, activeIndex} = this.state
hasAuth = index => {
const {videoList} = this.state
if (this.hasAuth(activeIndex)) {
this.setPlayerSrc(videoList[activeIndex]['play_url'])
}
}
let lesson = videoList[index]
hasAuth = index => {
const {videoList} = this.state
if (lesson['video_auth']) {
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 {
this.setState({
isAuth: false
})
return false
Toast.info(msg, 2, null, 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(
toHref,
{
to: 'classify'
}
) : history.go(-1)
}}/>
<Loading isLoading={this.state.isLoading}>
<div className="video">
<video className={'video-js'} ref={el => this.video = el}
webkit-playsinline="true"
playsInline={true}
x-webkit-airplay="allow"
x5-video-player-type="h5">
<source src={'/'} type='application/x-mpegURL'/>
</video>
{
!isAuth && !!videoList[activeIndex]['is_class'] && (
<div className="purchase-box">
<div className='hint'>您尚未购买该课时,请购买后学习。</div>
<div className='btns'>
<button
type='button'
onClick={this.tobuy}
className='purchase-class'
>
¥{salePrice} 购买课程
</button>
<button
type='button'
onClick={this.toSingleset.bind(this, videoList[activeIndex])}
className='purchase-episode'
>
¥{videoList.length && videoList[activeIndex]['class_price']} 购买单集
</button>
</div>
</div>
)
}
{
!isAuth && !!course.is_aist && (
<div className="is-aist-box">
<i className={'iconfont iconiconfront-21'}></i>
<p className={'time'}>{videoList[activeIndex]['aist_start_time']}</p>
<p className={'time'}>请耐心等待...</p>
</div>
)
}
</div>
<div className='tab'>
<div>
<NavLink to={{pathname: `${match.url}/video`, search: `?id=${this.courseID}`}}
replace
activeClassName='active'
>视频</NavLink>
</div>
<div>
<NavLink to={{pathname: `${match.url}/datum`, search: `?id=${this.courseID}`}}
replace
activeClassName='active'
>资料</NavLink>
</div>
</div>
{/*单集购买*/}
{
singleBox &&
<Single
courseId={course.course_id}
singleBox={this.state.singleBox}
boxHide={this.boxHide}
data={this.state.singMess}
singleType={this.state.singleType}
vcourseId={course.v_course_id}
videoId={this.state.singMess.video_id}
check={this.check}
title={this.state.singMess.course_tile}/>
}
{/* 单集购买成功 */}
{
singleType !== 1 &&
<SingleSuccess
courseId={course.course_id}
boxHide={this.boxHide}
data={this.state.singMess}
singleType={singleType}
vcourseId={course.v_course_id}
videoId={this.state.singMess.video_id}
nowPrice={this.state.nowPrice}
laterPrice={this.state.laterPrice}
/>
}
</Loading>
<Switch>
<Redirect exact from={'/play'} to={{
pathname: '/play/video',
search: location.search
}}/>
<Route
path={`${match.path}/video`}
render={props => {
return (
<VideoCatalog
activeIndex={this.state.activeIndex}
selectVideo={this.selectVideo}
videoCatalog={videoList}
isAist={course.is_aist}
{...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}
})
}
render() {
let {match, location, history} = this.props
const {
videoList,
activeIndex,
isAuth,
salePrice,
course,
singleBox,
singleType,
showLimitFreePopup,
limitFreePopup,
isShowNeverShowPopupOption
} = 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(
toHref,
{
to: 'classify'
}
) : history.go(-1)
}}/>
<Loading isLoading={this.state.isLoading}>
<div className="video">
<video className={'video-js'} ref={el => this.video = el}
webkit-playsinline="true"
playsInline={true}
x-webkit-airplay="allow"
x5-video-player-type="h5">
<source src={'/'} type='application/x-mpegURL'/>
</video>
{
!isAuth && !!videoList[activeIndex]['is_class'] && (
<div className="purchase-box">
<div className='hint'>您尚未购买该课时,请购买后学习。</div>
<div className='btns'>
<button
type='button'
onClick={this.tobuy}
className='purchase-class'
>
¥{salePrice} 购买课程
</button>
<button
type='button'
onClick={this.toSingleset.bind(this, videoList[activeIndex])}
className='purchase-episode'
>
¥{videoList.length && videoList[activeIndex]['class_price']} 购买单集
</button>
</div>
</div>
)
}
{
!isAuth && !!course.is_aist && (
<div className="is-aist-box">
<i className={'iconfont iconiconfront-21'}></i>
<p className={'time'}>{videoList[activeIndex]['aist_start_time']}</p>
<p className={'time'}>请耐心等待...</p>
</div>
)
}
</div>
<div className='tab'>
<div>
<NavLink to={{pathname: `${match.url}/video`, search: `?id=${this.courseID}`}}
replace
activeClassName='active'
>视频</NavLink>
</div>
<div>
<NavLink to={{pathname: `${match.url}/datum`, search: `?id=${this.courseID}`}}
replace
activeClassName='active'
>资料</NavLink>
</div>
</div>
{/*单集购买*/}
{
singleBox &&
<Single
courseId={course.course_id}
singleBox={this.state.singleBox}
boxHide={this.boxHide}
data={this.state.singMess}
singleType={this.state.singleType}
vcourseId={course.v_course_id}
videoId={this.state.singMess.video_id}
check={this.check}
title={this.state.singMess.course_tile}/>
}
{/* 单集购买成功 */}
{
singleType !== 1 &&
<SingleSuccess
courseId={course.course_id}
boxHide={this.boxHide}
data={this.state.singMess}
singleType={singleType}
vcourseId={course.v_course_id}
videoId={this.state.singMess.video_id}
nowPrice={this.state.nowPrice}
laterPrice={this.state.laterPrice}
/>
}
</Loading>
<Switch>
<Redirect exact from={'/play'} to={{
pathname: '/play/video',
search: location.search
}}/>
<Route
path={`${match.path}/video`}
render={props => {
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>
);
}
}
export default connect(
state => ({user: state.user}),
null
state => ({user: state.user}),
null
)(Video);
$tabHeight: 44px;
.play {
.video {
width: 100%;
height: 215px;
background-color: $black;
position: relative;
.video {
width: 100%;
height: 215px;
background-color: $black;
position: relative;
.video-js {
width: 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;
}
}
}
.video-js {
width: 100%;
height: 100%;
.purchase-box {
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;
.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;
justify-content: space-around;
}
.purchase-class {
@include button;
background-color: $white;
color: $color_FF4000;
}
.purchase-episode {
@include button;
background-color: $bg_FF4000;
color: $white;
}
.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;
}
}
.is-aist-box {
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;
}
&.vjs-has-started {
.vjs-custom-play-button-cover {
bottom: 2.9em;
}
}
video {
width: 100%;
height: 100%;
&.vjs-playing {
.vjs-custom-play-button-cover {
display: none;
}
}
}
.tab {
height: $tabHeight;
max-height: $tabHeight;
line-height: $tabHeight;
text-align: center;
background: #fff;
flex: 1 0 auto;
.purchase-box {
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;
.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;
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 {
flex: 1 0 auto;
}
.is-aist-box {
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 {
display: inline-block;
height: $tabHeight;
font-size: $font_16;
border-bottom: 1px solid transparent;
video {
width: 100%;
height: 100%;
}
}
.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 {
border-bottom: 1px solid $active;
}
}
a {
display: inline-block;
height: $tabHeight;
font-size: $font_16;
border-bottom: 1px solid transparent;
&.active {
border-bottom: 1px solid $active;
}
}
}
.active {
color: $active;
.active {
color: $active;
.iconiconfront-74 {
color: $color_555;
}
.iconiconfront-74 {
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 {
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;
.progress-container {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
li {
flex: 1;
.title {
font-size: 14px;
color: #00838F;
line-height: 20px;
text-align: center;
flex: 1;
margin-bottom: 10px;
}
.number {
font-size: 15px;
color: #00656F;
text-align: center;
.num {
font-size: 33px;
color: #00656F;
line-height: 30px;
text-align: center;
margin-bottom: 20px;
}
}
}
}
.progress-container {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
li {
flex: 1;
.title {
font-size: 14px;
color: #00838F;
line-height: 20px;
text-align: center;
flex: 1;
margin-bottom: 10px;
}
.number {
font-size: 15px;
color: #00656F;
text-align: center;
.num {
font-size: 33px;
color: #00656F;
}
}
}
.share-container {
.title {
position: relative;
text-align: center;
font-size: 14px;
color: #00838F;
margin-bottom: 25px;
&::before {
position: absolute;
top: 50%;
left: 30px;
transform: translateY(-50%);
content: '';
display: block;
width: 70px;
height: 1px;
background: #77c4bf;
}
.share-container {
.title {
position: relative;
text-align: center;
font-size: 14px;
color: #00838F;
margin-bottom: 25px;
&::before {
position: absolute;
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;
}
}
}
&::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;
.close {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -63px;
color: #fff;
font-size: 30px;
li {
font-size: 12px;
color: #00838F;
.iconfont {
font-size: 40px;
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 {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
touch-action: none;
z-index: 100;
.free-popup {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 290px;
height: 366px;
border-radius: 5px !important;
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 [
exact: true,
component: loadable(() => import('@/components/college/courseList'))
},
//限时免费落地页
{
path:'/free',
exact: true,
component: loadable(() => import(/*limit-free*/'@/components/limit-free'))
}
]
import jsCookie from "js-cookie";
import {
differenceInDays,
differenceInHours,
differenceInMinutes,
differenceInSeconds
} from 'date-fns'
export const getParam = (key, str) => {
const _s = str ? str : location.href;
const re = new RegExp(`(?:\\?|#|&)(${key})=([^=&#\\?]+)`, 'ig');
let found;
return (found = re.exec(_s)) ? found[2] : null;
const _s = str ? str : location.href;
const re = new RegExp(`(?:\\?|#|&)(${key})=([^=&#\\?]+)`, 'ig');
let found;
return (found = re.exec(_s)) ? found[2] : null;
}
const html = content => ({__html: htmlDecode(content)})
const html = content => ({
__html: htmlDecode(content)
})
const htmlDecode = content => {
let e = document.createElement('div');
e.innerHTML = content;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
let e = document.createElement('div');
e.innerHTML = content;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
//加载网易易盾辅助函数
function getTimestamp(msec) {
msec = !msec && msec !== 0 ? msec : 1
return parseInt((new Date()).valueOf() / msec, 10)
msec = !msec && msec !== 0 ? msec : 1
return parseInt((new Date()).valueOf() / msec, 10)
}
function loadScript(src, cb) {
var head = document.head || document.getElementsByTagName('head')[0]
var script = document.createElement('script')
var head = document.head || document.getElementsByTagName('head')[0]
var script = document.createElement('script')
cb = cb || function () {
}
cb = cb || function () {
}
script.type = 'text/javascript'
script.src = src
script.type = 'text/javascript'
script.src = src
if (!('onload' in script)) {
script.onreadystatechange = function () {
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
this.onreadystatechange = null
cb(script)
}
if (!('onload' in script)) {
script.onreadystatechange = function () {
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
this.onreadystatechange = null
cb(script)
}
}
script.onload = function () {
this.onload = null
cb(script)
}
script.onload = function () {
this.onload = null
cb(script)
}
head.appendChild(script)
head.appendChild(script)
}
function initCaptcha(cb) {
if (window.initNECaptcha) {
cb()
} else {
const url = '//cstaticdun.126.net/load.min.js' + '?t=' + getTimestamp(1 * 60 * 1000)
loadScript(url, cb)
}
if (window.initNECaptcha) {
cb()
} else {
const url = '//cstaticdun.126.net/load.min.js' + '?t=' + getTimestamp(1 * 60 * 1000)
loadScript(url, cb)
}
}
export const is_weixin = () => {
var ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger') {
return true;
}
return false;
var ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger') {
return true;
}
return false;
}
function validateTel(tel) {
return /^1[3-9](\d{9})$/.test(tel)
return /^1[3-9](\d{9})$/.test(tel)
}
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,}))$/;
return re.test(String(email).toLowerCase());
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());
}
const browser = (function () {
const ua = navigator.userAgent
return {
isWeixin: /MicroMessenger/i.test(ua),
isAndroid: /Android/i.test(ua),
isIOS: /\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(ua),
isIPad: /iPad/i.test(ua),
isAndroidApp: /Android/i.test(ua) && getParam('version'),
isIOSApp: /iPhone/i.test(ua) && getParam('version')
}
const ua = navigator.userAgent
return {
isWeixin: /MicroMessenger/i.test(ua),
isAndroid: /Android/i.test(ua),
isIOS: /\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(ua),
isIPad: /iPad/i.test(ua),
isAndroidApp: /Android/i.test(ua) && getParam('version'),
isIOSApp: /iPhone/i.test(ua) && getParam('version')
}
})()
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 {html, initCaptcha, validateTel, validateEmail, browser, isLogin}
export {default as SendMessageToApp} from './app'
export {
default as http
}
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