Commit f258f7d3 by xuzhenghua

python小课

parent 217f0976
......@@ -1846,6 +1846,11 @@
"negotiator": "0.6.1"
}
},
"ace-builds": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.4.7.tgz",
"integrity": "sha512-gwQGVFewBopRLho08BfahyvRa9FlB43JUig5ItAKTYc9kJJsbA9QNz75p28QtQomoPQ9rJx82ymL21x4ZSZmdg=="
},
"acorn": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
......@@ -4686,6 +4691,11 @@
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
},
"diff-match-patch": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.4.tgz",
"integrity": "sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg=="
},
"diffie-hellman": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
......@@ -9235,6 +9245,11 @@
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
"lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
},
"lodash.isarguments": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
......@@ -9245,6 +9260,11 @@
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
},
"lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
},
"lodash.keys": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
......@@ -12051,6 +12071,18 @@
"scheduler": "^0.13.6"
}
},
"react-ace": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/react-ace/-/react-ace-8.0.0.tgz",
"integrity": "sha512-EvU14vXbZpAenb1ZVKdn8yTQs/shZ9RghFulHtt67bBXT6sjrNHcfOEXHYtSEmwMb6pQVVNNuulzzd8o+Uouig==",
"requires": {
"ace-builds": "^1.4.6",
"diff-match-patch": "^1.0.4",
"lodash.get": "^4.4.2",
"lodash.isequal": "^4.5.0",
"prop-types": "^15.7.2"
}
},
"react-app-polyfill": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-0.2.2.tgz",
......
......@@ -57,6 +57,7 @@
"qrcode": "^1.3.3",
"qs": "^6.7.0",
"react": "^16.8.6",
"react-ace": "^8.0.0",
"react-app-polyfill": "^0.2.2",
"react-copy-to-clipboard": "^5.0.1",
"react-dev-utils": "^8.0.0",
......
......@@ -33,7 +33,7 @@ class HeaderBar extends Component {
}
render() {
const { toHref } = this.props
const { toHref, home } = this.props;
return (
<div className="detail-header" style={{...this.props.style}}>
{
......@@ -57,6 +57,10 @@ class HeaderBar extends Component {
this.props.delete &&
<i className='iconfont iconiconfront-56' onClick={this.props.toDelete}></i>
}
{
home &&
<i className="iconfont iconshouye-xianxing"></i>
}
</div>
);
}
......
......@@ -268,6 +268,7 @@ function CourseList({modules, toDetail}) {
}
return (
<div className='category'>
<Link className="more" to='/python'>python ></Link>
<h2 className="title">{modules.name}</h2>
{
modules.show_more === 1 &&
......
import React, { Component } from 'react'
import { connect } from 'react-redux';
import {http, getParam} from '@/utils'
import PythonDes from './pythomDes'
import PythonStudy from './pythonStudy'
import {Toast} from 'antd-mobile'
@connect(state => ({
user: state.user
}))
class Python extends Component {
constructor(props) {
super(props);
this.state = {
isPay: 1,
}
}
componentDidMount() {
this.fetchCourseInfo();
}
fetchCourseInfo = () => {
const id = getParam('id');
// http.get(`${API.home}/m/course/detail/${id}`).then((res) => {
// const {data, code} = res.data;
// if (code === 200) {
//
// this.setState({
// // TODO
// // isPay: data.course_info.is_pay
// isPay: 1
// })
// }
// });
}
render() {
const {isPay} = this.state;
const {user: {hasError}} = this.props;
return (
<div>
{
isPay === 0 && <PythonDes ></PythonDes>
}
{
isPay === 1 && <PythonStudy></PythonStudy>
}
</div>
)
}
}
export default Python
import React, { Component } from 'react'
import './index.scss'
export default class Description extends Component {
render() {
return (
<div className={'description'}>
<img className={'left'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/left.png" alt=""/>
<img className={'right'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/right.png" alt=""/>
<p className={'title'}> / / / </p>
<p className={'sub__title'}>对话式交互教学+课后实操,20节课全面掌握Python基础语法</p>
<img src={'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/diannao.png'} />
{
this.props.list.map((item, index)=>{
return <DesList item={item} key={index}></DesList>
})
}
</div>
)
}
}
function DesList(props) {
const {url, title, subTitle} = props.item;
return (
<div className={'des__container'}>
<img src={url} alt=""/>
<div>
<p className={'item__title'}>{title}</p>
<p className={'item__sub'}>{subTitle}</p>
</div>
</div>
)
}
.description {
width: 100%;
background: #0099ff;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
padding: 32px 0 38px 0;
position: relative;
.left {
position: absolute;
width: 50px;
height: 144px;
left: 0;
top: 18px;
}
.right {
position: absolute;
right: 0;
bottom: 4px;
width: 48px;
height: 132px;
}
.title {
font-size: 22px;
font-weight: 600;
color: rgba(255, 255, 255, 1);
margin-bottom: 12px;
}
.sub__title {
font-size: 12px;
font-weight: 300;
color: rgba(255, 255, 255, 1);
margin-bottom: 40px;
}
img {
width: 290px;
height: 170px;
}
.des__container {
width: 100%;
height: 64px;
display: flex;
justify-content: flex-start;
align-items: center;
padding-left: 50px;
margin-top: 28px;
img {
width: 64px;
height: 64px;
margin-right: 12px;
}
.item__title {
font-size: 16px;
font-weight: 600;
color: rgba(255, 255, 255, 1);
margin-bottom: 10px;
line-height: 16px;
}
.item__sub {
font-size: 12px;
font-weight: 400;
color: rgba(255, 255, 255, 1);
line-height: 12px;
}
}
}
import React, { Component } from 'react'
import './index.scss'
export default class NoWorry extends Component {
render() {
return (
<div className={'worry__container'}>
<img className={'left'} src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/worry_left.png" alt=""/>
<p className={'title'}> / / / </p>
<p className={'sub__title'}>全新的课程形式,轻松、有趣的课程内容,解除你所有的担忧</p>
{
this.props.list.map((item, index)=>{
return (
<WorryItem item={item} key={index}></WorryItem>
)
})
}
</div>
)
}
}
function WorryItem(props) {
const {url, title, subTitle} = props.item
return (
<div className={'item__container'}>
<div className={'head'}></div>
<img src={url} alt=""/>
<p className={'title'}>{title}</p>
<p className={'des'}>{subTitle}</p>
</div>
)
}
.worry__container {
padding: 32px 0 44px 0;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
position: relative;
.left {
position: absolute;
left: 0;
top: 150px;
width: 40px;
height: 220px;
}
.title {
font-size: 22px;
line-height: 22px;
font-weight: 600;
color: rgba(0, 153, 255, 1);
margin-bottom: 12px;
}
.sub__title {
font-size: 12px;
line-height: 12px;
font-weight: 300;
color: rgba(0, 153, 255, 1);
margin-bottom: 40px;
}
.item__container {
width: 310px;
height: 214px;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 6px 12px 0px rgba(0, 0, 0, 0.03);
border-radius: 4px;
margin-bottom: 22px;
display: flex;
flex-direction: column;
justify-content: flex-start;
padding: 0 26px;
align-items: center;
z-index: 9;
.head {
width: 310px;
height: 4px;
background: rgba(0, 153, 255, 1);
border-radius: 4px 4px 0 0;
margin-bottom: 12px;
}
img {
width: 58px;
height: 58px;
}
.title {
font-size: 16px;
line-height: 16px;
font-weight: 600;
color: rgba(82, 92, 101, 1);
margin: 16px 0 12px 0;
}
.des {
font-size: 12px;
font-weight: 400;
color: rgba(82, 92, 101, 1);
line-height: 20px;
}
}
}
import React, { Component } from 'react'
import './index.scss'
import Description from './Description/index.js';
import NoWorry from './NoWorry/index.js';
export default class PythonDes extends Component {
constructor(props) {
super(props);
this.state = {
defineList: [
{
titleUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/trophy.png',
title: '排名第1的编程语言',
subTitle: '2018世界编程语言排行榜中,Python排名第1',
subWidth: '180px',
bottomUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/program_lan.png',
desInfo: {
width: '240px',
height: '170px',
}
},
{
titleUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/kaifa.png',
title: '开发快速、简单易掌握',
subTitle: '严谨的代码编写格式,语法格式简单易理解完成一个相同的任务',
subWidth: '260px',
bottomUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/kuaisu.png',
desInfo: {
width: '212px',
height: '106px',
}
},
{
titleUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/lingyu.png',
title: '适用领域广',
subTitle: 'Python工程师可从事多领域编程工作,人才年需求增长6倍',
subWidth: '230px',
bottomUrl: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/jiandan.png',
desInfo: {
width: '234px',
height: '106px',
}
}
],
desList: [
{url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/xingshi.png', title: '全新课程形式', subTitle: '对话式交互教学,轻松、生动、不无聊'},
{url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/huanjing.png', title: '在线编程环境', subTitle: '无需安装任何编程软件'},
{url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/rumen.png', title: '20天零基础入门', subTitle: '降低学习门槛,20天入门人工智能'},
],
worryList: [
{url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/jiechu.png', title: '初次接触,担心学不会', subTitle: '本课程专门为零基础的你打造,全篇通过最白话沟通交流的方式进行讲解,无论你有无编程经验都可以轻松理解并且掌握。'},
{url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/xuexi.png', title: '想学习,没有坚持下来', subTitle: '以故事性的方式编写学习内容, 把生硬的知识点有趣化。精美的图片+幽默的文字+代码编写让你越学越向学。'},
{url: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/zhishidian.png', title: '知识点掌握了,不知如何运用', subTitle: '每节课的知识点都设有代码编写部分,每节课课后都有课后实操。有多次代码编写练习的机会,助你真正学以致用。'},
],
}
}
render() {
const {defineList, desList, worryList} = this.state;
return (
<div className={'python__des'}>
<div className={'des__start'}></div>
<div className={'python__define'}>
<img className={'left__decorate'} src={'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/left__decorate.png'}></img>
<img className={'right__decorate'} src={'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/right__decorate.png'}></img>
<p className={'define__title'}> / / / Python</p>
{
defineList.map((item,index) => {
return <DefineItem item={item} key={index}></DefineItem>
})
}
</div>
<div className={'course__introduce'}></div>
<div className={'bottom__btn_group'}>
<div className={'course__price'}>
<div className={'money'}>199<span style={{fontSize: '18px'}}></span></div>
<div className={'discount'}>
限时特惠
<div className={'triangle'}></div>
</div>
</div>
<div className={'btn__group'}>
<div className={'try__study'}>免费试学</div>
<div className={'sign__now'}>立即报名</div>
</div>
</div>
<Description list={desList}></Description>
<NoWorry list={worryList}></NoWorry>
</div>
)
}
}
function DefineItem(props) {
const {item, item: {desInfo}} = props;
return (
<div className={'number_one'}>
<img className={'trophy'} src={item.titleUrl}></img>
<p className={'item__title'}>{item.title}</p>
<p className={'item__subtitle'} style={{width: item.subWidth}}>{item.subTitle}</p>
<img style={{width: desInfo.width, height: desInfo.height}} src={item.bottomUrl}></img>
</div>
)
}
.python__des {
width: 100vw;
height: 100vh;
padding-bottom: 60px;
overflow: auto;
.des__start {
width: 100%;
height: 258px;
background: url("https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/h5_python_class/head_img.png")
center center no-repeat;
background-size: contain;
}
.python__define {
position: relative;
padding-top: 28px;
.define__title {
font-size: 22px;
line-height: 22px;
font-weight: 600;
color: rgba(0, 153, 255, 1);
text-align: center;
text-align-last: center;
margin: 0 auto 40px;
}
.number_one {
width: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
margin-bottom: 30px;
}
// 公共
.trophy {
width: 75px;
height: 75px;
margin-bottom: 12px;
}
.item__title {
font-size: 16px;
line-height: 16px;
font-weight: 600;
color: rgba(82, 92, 101, 1);
margin-bottom: 12px;
}
.item__subtitle {
font-size: 12px;
font-weight: 400;
color: rgba(82, 92, 101, 0.8);
text-align: center;
text-align-last: center;
margin-bottom: 16px;
}
.left__decorate {
position: absolute;
left: 0;
top: -50px;
width: 60px;
height: 216px;
}
.right__decorate {
position: absolute;
right: 0;
top: 156px;
width: 44px;
height: 180px;
}
}
.bottom__btn_group {
width: 100%;
height: 56px;
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 99;
padding: 0 14px;
background: #fff;
.course__price {
width: 100px;
font-size: 24px;
font-weight: 600;
color: rgba(255, 33, 33, 1);
position: relative;
}
.discount {
width: 54px;
height: 22px;
background: rgba(248, 60, 46, 1);
border-radius: 2px;
display: flex;
justify-content: center;
align-items: center;
font-size: 10px;
font-weight: 500;
color: rgba(255, 255, 255, 1);
position: absolute;
left: 46px;
top: -18px;
.triangle {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #FB3A22;
position: absolute;
bottom: -5px;
left: 8px;
}
}
.btn__group {
display: flex;
justify-content: center;
align-items: center;
.try__study {
width: 100px;
height: 38px;
border: 1px solid rgba(0, 153, 255, 1);
border-radius: 19px;
box-sizing: border-box;
font-size: 16px;
font-weight: 600;
color: rgba(0, 153, 255, 1);
display: flex;
justify-content: center;
align-items: center;
}
.sign__now {
width: 100px;
height: 38px;
background: rgba(0, 153, 255, 1);
border-radius: 19px;
box-sizing: border-box;
font-size: 16px;
font-weight: 600;
color: rgba(255, 255, 255, 1);
display: flex;
justify-content: center;
align-items: center;
margin-left: 12px;
}
}
}
}
import React, { Component } from 'react';
import {Accordion, Toast} from 'antd-mobile';
import { HeaderBar } from '@/common';
import { http,getParam } from '@/utils';
import './index.scss';
import {connect} from "react-redux";
class PythonStudy extends Component {
constructor(props) {
super(props);
this.state = {
courseInfo:'',
syllabus:'',
learning:''
};
}
componentDidMount() {
this.fetchCourseDetail();
}
fetchCourseDetail = () => {
http.get(`${API['home']}/web/it_detail?course_id=${getParam('id')}&is_pay=1`).then(res => {
const {data, code,msg} = res.data;
if (code === 200) {
this.setState({
courseInfo: data.course_info,
syllabus: data.syllabus,
learning: data.learning
})
} else {
Toast.info(msg, 2)
}
});
}
Change = (data) => {
let cn = ["一", "二", "三", "四", "五", "六", "七", "八", "九", '十'];
let newStr = ''
let str = data.toString()
let ci = Number(str) % 10
let cs = Math.floor(Number(str) / 10)
let cv = ''
if (str.length > 1) {
if (cs == 1) {
cv = ci >= 1 ? cn[9] + cn[ci - 1] : cn[9]
} else {
cv = ci > 1 ? cn[cs - 1] + cn[9] + cn[ci - 1] : cn[cs - 1] + cn[9]
}
} else {
cv = cn[ci - 1]
}
newStr = str.replace(str, cv)
return newStr;
}
onChange = (key) => {
console.log(key);
}
render() {
const {user} = this.props;
const uid = user && user.data && user.data.uid
const {courseInfo,syllabus,learning } = this.state;
return (
<div className="python-study">
<HeaderBar title='Python基础语法' arrow={true} />
<div className="python-study__header">
<div className="python-study__course">
<h2 className="python-study__course-name">Python人工智能</h2>
<p className="python-study__course-contact">
<span>{courseInfo.contact_type == 1 ? '上课请加QQ学习群':'添加助教微信入群'}{courseInfo.course_qq}</span>
<span>并备注您的学号:{uid}</span>
</p>
</div>
{
learning.schedule==0 &&
<div className="python-study__progress">
<h2 className="python-study__progress-title">学习进度</h2>
<div className="python-study__progress-bar">
<i style={{width: learning.schedule+'%'}}></i>
<span className="python-study__progress-tip" style={{left: learning.schedule+'%'}}>{learning.schedule+'%'}</span>
</div>
</div>
}
</div>
<Accordion
defaultActiveKey="0"
className="python-study__stage"
onChange={this.onChange}
>
{
syllabus && syllabus.length>0 && syllabus.map((syllabusItem,index)=>{
let header = `第${this.Change(syllabusItem.stage)}阶段:${syllabusItem.name}`
return(
<Accordion.Panel header={header} className="pad">
{
syllabusItem.lessons && syllabusItem.lessons.length>0 && syllabusItem.lessons.map((lessonsItem,index)=> {
return(
<div>
<h2 className="python-study__pass">
{lessonsItem.shut} {lessonsItem.name}
{
lessonsItem.complete == 1 &&
<i className="python-study__pass-tag">闯关完成</i>
}
</h2>
{
lessonsItem.questions && lessonsItem.questions.length>0 && lessonsItem.questions.map((item,index)=> {
return (
<div className="python-study__subject">
<img className="python-study__subject-icon" src={item.icon} alt="" />
{
item.is_unlock == 1 && item.complete == 1 &&
<i className="python-study__subject-status" data-status="complete"></i>
}
{
item.is_unlock == 1 && item.complete == 0 &&
<i className="python-study__subject-status" data-status="lock"></i>
}
<div className="python-study__subject-content">
<h2 className="python-study__subject-title">{item.name}</h2>
{
item.is_must == 1 &&
<span className="python-study__subject-tag">必做练习</span>
}
</div>
</div>
)
})
}
{/*<div className="python-study__subject">*/}
{/*<i className="python-study__subject-icon"></i>*/}
{/*<i className="python-study__subject-status" data-status="complete"></i>*/}
{/*<div className="python-study__subject-content">*/}
{/*<h2 className="python-study__subject-title">基础练习基基础练习基础练习基础练习基础练习</h2>*/}
{/*<span className="python-study__subject-tag">必做练习</span>*/}
{/*</div>*/}
{/*</div>*/}
{/*<div className="python-study__subject" data-status="lock">*/}
{/*<i className="python-study__subject-icon"></i>*/}
{/*<i className="python-study__subject-status" data-status="lock"></i>*/}
{/*<div className="python-study__subject-content" >*/}
{/*<h2 className="python-study__subject-title" data-status="lock">基础练习基基础练习基础练习基础练习基础练习</h2>*/}
{/*<span className="python-study__subject-tag">必做练习</span>*/}
{/*</div>*/}
{/*</div>*/}
</div>
)
})
}
</Accordion.Panel>
)
})
}
</Accordion>
<button className="python-study__button">开始学习</button>
</div>
)
}
}
export default connect(
state => ({user: state.user}),
null
)(PythonStudy);
.am-accordion.python-study__stage .am-accordion-item .am-accordion-header {
height: 44px;
padding-left: 13px;
font-size: 15px;
font-weight: 600;
color: #333;
background-color: #CFDBE5;
}
html:not([data-scale]) .am-accordion.python-study__stage .am-accordion-item .am-accordion-content .am-accordion-content-box::after {
display: none;
}
.am-accordion.python-study__stage .am-accordion-item .am-accordion-header i {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/pythonCourse/h5/subject-icon-arrow.png');
}
.python-study {
height: 100%;
background-color: #F4F5F6;
}
.python-study__header {
margin: 10px 10px 18px;
border-radius: 5px;
background-color: #fff;
overflow: hidden;
}
.python-study__course {
display: flex;
align-items: center;
justify-content: space-between;
height: 55px;
padding: 0 12px;
background-color: #1A9BFC;
}
.python-study__course-name {
font-size: 15px;
font-weight: 600;
color: #fff;
}
.python-study__course-contact {
display: inline-flex;
flex-direction: column;
align-items: flex-end;
font-size: 12px;
color: rgba(255,255,255,.8);
}
.python-study__progress {
height: 66px;
padding: 0 12px;
}
.python-study__progress-title {
font-size: 14px;
font-weight: 600;
color: rgba(51,51,51,.6);
line-height: 39px;
}
.python-study__progress-bar {
position: relative;
height: 3px;
margin: 11px 0 13px;
border-radius: 2px;
background-color: rgba(207,219,229,.6);
i {
position: absolute;
width: 10%;
height: 100%;
border-radius: 2px;
background-color: #1A9BFC;
}
}
.python-study__progress-tip {
position: absolute;
top: -26px;
width: 36px;
margin-left: -18px;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
color: #fff;
text-align: center;
line-height: 18px;
background-color: #1A9BFC;
&::after {
content: '';
position: absolute;
left: 50%;
bottom: -8px;
margin-left: -4px;
border: 4px solid;
border-color: #1A9BFC transparent transparent;
}
}
.python-study__stage {
margin: 15px 10px 0;
border-radius: 4px;
overflow: hidden;
}
.python-study__pass {
margin: 0 13px;
padding-top: 7px;
font-size: 14px;
font-weight: 600;
color: #333;
line-height: 40px;
}
.python-study__pass-tag {
display: inline-block;
width: 62px;
margin-left: 6px;
border-radius: 11px;
font-size: 12px;
font-style: normal;
font-weight: 600;
color: rgba(26,155,252,1);
text-align: center;
line-height: 21px;
background-color: rgba(26,155,252,.1);;
}
.python-study__subject {
height: 67px;
margin: 0 8px 8px;
padding: 6px;
border-radius: 4px;
box-sizing: border-box;
background-color: rgba(247,248,249,1);
&[data-status="lock"] {
background-color: rgba(247,248,249,.6);
}
}
.python-study__subject-icon {
float: left;
width: 55px;
height: 55px;
border-radius: 4px;
background-color: #fff;
overflow: hidden;
}
.python-study__subject-status {
position: absolute;
right: 17px;
width: 21px;
height: 21px;
background-size: cover;
&[data-status="complete"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/pythonCourse/h5/subject-icon-0.png');
}
&[data-status="lock"] {
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/pythonCourse/h5/subject-icon-1.png');
}
}
.python-study__subject-content {
height: 100%;
margin-left: 55px;
padding: 0 33px 0 12px;
}
.python-study__subject-title {
font-size: 14px;
color: #333;
line-height: 18px;
&[data-status="lock"] {
color: #525C65;
}
}
.python-study__subject-tag {
display: inline-block;
padding: 0 4px;
border-radius: 2px;
font-size: 12px;
color: rgba(82,92,101,.1);
line-height: 18px;
background-color: rgba(82,92,101,.1);
}
.python-study__button {
position: fixed;
bottom: 0;
width: 100%;
height: 50px;
border-style: none;
box-sizing: border-box;
font-size: 16px;
font-weight: 600;
color: #fff;
text-align: center;
background-color: #1A9BFC;
}
\ No newline at end of file
import React, { Component } from 'react';
import {CopyToClipboard} from 'react-copy-to-clipboard';
import AceEditor from 'react-ace';
import { Toast } from "antd-mobile"
import {HeaderBar} from '@/common';
import { browser, http, getParam } from '@/utils';
import './index.scss';
import 'ace-builds/src-noconflict/mode-python';
import 'ace-builds/src-noconflict/theme-dracula';
class PythonClass extends Component {
constructor(props) {
super(props);
this.state = {
isWechat: browser.isWeixin,
isShare: true,
type: '1', // 1:课后习题,2:课堂习题
entryMode: 1, // 0:扫码页,1:落地页,2:直接进入
isExecute: false,
isCopy: false,
command: 'http://m.julyedu.com/python?from=python',
data: {}
}
}
componentDidMount() {
this.handleFetchInfo();
this.initPageStatus();
}
initPageStatus = () => {
if(getParam('from') === 'barcode') {
this.setState({
entryMode: 0
});
}
if(getParam('from') === 'python') {
this.setState({
entryMode: 2
});
}
if(getParam('type') === '1') {
this.setState({
isShare: true
});
}
if(getParam('type') === '2') {
this.setState({
isShare: false
});
}
this.setState({
type: getParam('ques') || '1'
});
}
handleFetchInfo = () => {
const id = getParam('id') || 10;
http.get(`${API.home}/web/python/share/help/${id}`).then(res => {
console.log(res);
const { code, data } = res.data;
if(code === 200) {
this.setState({
data,
});
}
})
}
handleToSend = () => {
const { history } = this.props;
if(browser.isWeixin) {
this.setState({
entryMode: 1
});
history.push(`/python?id=${getParam('id')}&type=${getParam('type')}&ques=${getParam('ques')}&from=python`);
}
}
copyToSuccess = () => {
Toast.info('已复制链接,快去粘贴发给好友吧~');
this.setState({
isCopy: true
});
}
handleToExecute = () => {
this.setState({
isExecute: true
});
}
render() {
const { isWechat, isShare, isExecute, type, entryMode, command, isCopy, data } = this.state;
return (
<>
<HeaderBar
title='Python基础语法'
arrow={true}
home={true}
/>
<PythonContent
isWechat={isWechat}
isShare={isShare}
type={type}
isExecute={isExecute}
entryMode={entryMode}
isCopy={isCopy}
command={command}
data={data}
handleToExecute={this.handleToExecute}
handleToSend={this.handleToSend}
copyToSuccess={this.copyToSuccess}
/>
</>
);
}
}
function SelfAceEditor(props) {
return (
<AceEditor
mode="python"
theme="dracula"
readOnly={true}
showPrintMargin={false}
value={props.code}
style={{
width: '100%',
height: '100%'
}}
/>
)
}
function PythonContent(props) {
const {
isWechat,
isShare,
isExecute,
type,
entryMode,
isCopy,
command,
data: { head_img, nickname, code_lines, code, result, ques_name, course_name, video_name },
handleToSend,
copyToSuccess,
handleToExecute
} = props;
let labelName = '';
if(type === '1') {
labelName = `练习-${ques_name}`;
}
if(type === '2') {
labelName = `课堂-${video_name}`;
}
return (
<div className="python-container">
{/* 微信 */}
{
// (entryMode === 0 && isWechat) &&
// <div className="python-header">
// <p className="python-wechat__title">请点击右上角分享</p>
// <i className="iconfont iconyindao"></i>
// </div>
}
{/* 非微信 */}
{
// (entryMode === 0 && !isWechat) &&
// <div className="python-header">
// <p className="python-wechat__title">
// {isShare? '快分享给好友吧' : '快发给好友求助吧'}
// </p>
// </div>
}
{
(entryMode === 1 && isWechat) &&
<div className="python-popup">
<div className="python-header">
<p className="python-wechat__title">请点击右上角分享</p>
<i className="iconfont iconyindao"></i>
</div>
</div>
}
<div className="python-content">
<div className="python-user">
<div className="python-user__portrait">
<img src={head_img} alt=""/>
</div>
<h2 className="python-user__id">{nickname}</h2>
{/* 分享 */}
{
(entryMode === 0 && isShare) &&
<p className="python-user__desc">
完成了
<span>{labelName}</span>
</p>
}
{
(entryMode !== 0 && isShare) &&
<p className="python-user__desc">
<span>{course_name}</span>完成了<br />
{labelName}
</p>
}
{/* 求助 */}
{
(entryMode === 0 && !isShare) &&
<p className="python-user__desc">
<span>{labelName}</span>
遇到了困难
</p>
}
{
(entryMode !== 0 && !isShare) &&
<p className="python-user__desc">
<span>{course_name}</span>的<br />
<span>{labelName}</span>遇到了困
</p>
}
</div>
<h4 className="python-code__title">
{entryMode !== 0 && isShare? `这是Ta的第${code_lines}行代码` : '运行结果'}
</h4>
<div className="python-code__content">
<SelfAceEditor code={entryMode !== 0 && isShare? code : result} />
</div>
<h4 className="python-code__title">{entryMode === 0? '代码' : '运行结果'}</h4>
<div className="python-code__content">
{
entryMode === 0 &&
<SelfAceEditor code={code} />
}
{
entryMode !== 0 &&
<SelfAceEditor code={isExecute? result : ''} />
}
{
(entryMode !== 0 && isShare && !isExecute) &&
<button className="python-button python-button__execute" onClick={handleToExecute}>运行看看</button>
}
</div>
</div>
{
(entryMode === 0 && isWechat) &&
<button className="python-button python-button__study" onClick={handleToSend}>发给好友</button>
}
{
(entryMode === 0 && !isWechat && !isCopy) &&
<CopyToClipboard
text={command}
onCopy={copyToSuccess}
>
<button className="python-button python-button__study">发给好友</button>
</CopyToClipboard>
}
{
(entryMode === 0 && !isWechat && isCopy) &&
<button className="python-button python-button__study">已复制链接,快去粘贴发给好友吧~</button>
}
{
entryMode !== 0 &&
<button className="python-button python-button__study">我也要学Python</button>
}
</div>
);
}
export default PythonClass;
\ No newline at end of file
.python-container {
padding: 50px 8px 29px;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/pythonCourse/h5/python-bg.png');
background-size: cover;
}
.python-container--page {
// padding-top: 50px;
}
.python-header {
position: relative;
height: 100px;
padding-top: 34px;
box-sizing: border-box;
.iconfont {
position: absolute;
top: -6px;
right: 40px;
font-size: 38px;
color: #fff;
}
}
.python-wechat__title {
margin: 0;
font-size: 17px;
color: #FCFF1D;
text-align: center;
line-height: 1;
}
.python-content {
padding-bottom: 37px;
background-image: url('https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/pythonCourse/h5/python-content-bg.png');
background-size: cover;
}
.python-user {
position: relative;
margin: 0 5px;
padding-top: 45px;
border-bottom: 1px dashed #000;
}
.python-user__portrait {
position: absolute;
top: -30px;
left: 0;
right: 0;
width: 60px;
height: 60px;
margin: auto;
padding: 5px;
border-radius: 50%;
box-sizing: border-box;
background-color: #fff;
img {
display: block;
width: 100%;
}
}
.python-user__id {
margin: 0;
font-size: 15px;
font-weight: 500;
color: #111;
text-align: center;
line-height: 1;
}
.python-user__desc {
height: 48px;
margin: 4px 0;
font-size: 16px;
color: #333;
text-align: center;
span {
color: #2D57F0;
}
}
.python-code__title {
position: relative;
margin: 32px 16px 21px;
padding-left: 16px;
font-size: 17px;
font-weight: 600;
color: #2D56F0;
line-height: 1;
&:after {
content: '';
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 4px;
height: 12px;
margin: auto 0;
background-color: #2D56F0;
}
}
.python-code__content {
position: relative;
height: 171px;
margin: 0 16px;
padding: 0 10px;
border-radius: 5px;
border: 1px solid #67E4FF;
box-sizing: border-box;
font-size: 14px;
color: #fff;
background-color: #272822;
}
.python-button {
padding: 0;
border-style: none;
cursor: pointer;
outline: none;
}
.python-button__study {
display: block;
width: 233px;
height: 44px;
margin: 35px auto 0;
border-radius: 22px;
font-size: 16px;
font-weight: 500;
color: #2D56F0;
line-height: 44px;
background-color: #FFF95B;
box-shadow: 0px 5px 0px rgba(255,210,0,1);
}
.python-button__execute {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 110px;
height: 32px;
margin: auto;
border-radius: 16px;
font-size: 15px;
color: #fff;
line-height: 32px;
background-color: #0099FF;
}
.python-popup {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .3);
z-index: 99;
}
.ace_mobile-menu {
display: none;
}
\ No newline at end of file
......@@ -225,5 +225,18 @@ export default [
{
path: '/invite',
component: Invite,
}
},
// python 小课页面
{
path: '/python',
component: loadable(() => import(/* webpackChunkName: 'python-class'*/'@/components/python'))
},
{
path: '/pythonShare',
component: loadable(() => import('@/components/pythonShare'))
},
{
path: '/pythonStudy',
component: loadable(() => import('@/components/pythonStudy'))
},
]
......@@ -1434,6 +1434,11 @@ accepts@~1.3.4, accepts@~1.3.5:
mime-types "~2.1.18"
negotiator "0.6.1"
ace-builds@^1.4.6:
version "1.4.6"
resolved "https://registry.npm.taobao.org/ace-builds/download/ace-builds-1.4.6.tgz#ff6abd5f31472f33c1958ab99e0de6b63db3c964"
integrity sha1-/2q9XzFHLzPBlYq5ng3mtj2zyWQ=
acorn-dynamic-import@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278"
......@@ -3681,6 +3686,11 @@ detect-port-alt@1.1.6:
address "^1.0.1"
debug "^2.6.0"
diff-match-patch@^1.0.4:
version "1.0.4"
resolved "https://registry.npm.taobao.org/diff-match-patch/download/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1"
integrity sha1-asS1UjdGN2HE2vDcYD64aRJHRLE=
diff@^3.2.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
......@@ -6817,6 +6827,11 @@ lodash.debounce@^4.0.0:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.npm.taobao.org/lodash.get/download/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.isarguments@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
......@@ -6827,6 +6842,11 @@ lodash.isarray@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.npm.taobao.org/lodash.isequal/download/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.keys@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
......@@ -9237,6 +9257,17 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
react-ace@^8.0.0:
version "8.0.0"
resolved "https://registry.npm.taobao.org/react-ace/download/react-ace-8.0.0.tgz#e6fc155ec3cf240e92bdf2e156a50458a78ed0a4"
integrity sha1-5vwVXsPPJA6SvfLhVqUEWKeO0KQ=
dependencies:
ace-builds "^1.4.6"
diff-match-patch "^1.0.4"
lodash.get "^4.4.2"
lodash.isequal "^4.5.0"
prop-types "^15.7.2"
react-app-polyfill@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-0.2.2.tgz#a903b61a8bfd9c5e5f16fc63bebe44d6922a44fb"
......
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