Commit 0c2a2645 by zhanghaozhe

ml小程序

parent f77d1327
import React, { Component } from 'react';
import './index.scss'
import Container from './container'
import SingleAnswerQuestion from "@components/interactive-study/single-answer-question"
import Program from "@components/interactive-study/program"
import { WithFullSize } from "@/HOCs"
class InteractiveStudy extends Component {
singleIcon = 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/interactive_tutorial/study/single-answer-icon.png'
programIcon = 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/interactive_tutorial/study/program-icon.png'
state = {
options: [
'A. 程序向屏幕输出信息的过程,是人与计算机的单向沟通。',
'B. 程序向内部输入信息的过程。',
'C. 程序向内部输入信息的过程。',
],
img: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/weekend/bigdata/project/07.png'
}
componentDidMount() {
}
render() {
return (
<div id={'interactive-study'}>
<Container user={'https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/home/avatar_20191104.png'}
content={'Hi!初次见面,我叫小柒,是你在七月在线的课程导师。从现在开始,你就要跟着我一起学Python啦,请敲回车键继续课程。'}/>
<SingleAnswerQuestion user={this.singleIcon} topic={'请问,你会推荐哪个物品给用户C?'} options={this.state.options}
img={this.state.img}/>
<Program user={this.programIcon} code={"week = ['星期一', '星期二', '星期三']\nprint(123)"}/>
</div>
);
}
}
export default WithFullSize(InteractiveStudy);
\ No newline at end of file
#interactive-study {
background-color: #252529;
min-height: 100%;
}
\ No newline at end of file
import React, { Component } from 'react';
import './index.scss'
class Catalog extends Component {
render() {
return (
<div className={'catalog'}>
<div className="icon">
<img src="https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/interactive_tutorial/study/level1-title-icon.png"
alt=""/>
</div>
<div className="title">{this.props.title}</div>
</div>
);
}
}
export default Catalog;
\ No newline at end of file
.catalog {
display: flex;
padding-left: 12px;
margin-bottom: 38px;
font-size: 20px;
color: #FFD667;
align-items: center;
.icon {
padding-right: 10px;
line-height: 22px;
}
img {
width: 20px;
height: 22px;
vertical-align: middle;
}
.title {
padding-left: 19px;
}
}
\ No newline at end of file
export const questionType = {
text: 1,
image: 2,
singleAnswer: 3,
codeBlock: 4,
program: 5,
}
export const status = {
practice: '练习',
practicing: '练习中...',
startPractice: '开始练习',
resumePractice: '继续练习',
nextSection: '下一关',
}
\ No newline at end of file
...@@ -3,17 +3,16 @@ import './index.scss' ...@@ -3,17 +3,16 @@ import './index.scss'
class Container extends Component { class Container extends Component {
render() { render() {
const {user, content} = this.props const {user, content, children} = this.props
return ( return (
<div className={'container'}> <div className={'container'}>
{ <div className="user">
user && {
<div className="user"> user && <img className={'avatar'} src={user} alt=""/>
<img className={'avatar'} src={user} alt=""/> }
</div> </div>
}
<div className="divide"></div> <div className="divide"></div>
<div className="content">{content}</div> <div className="content">{content ? content : children}</div>
</div> </div>
); );
} }
......
...@@ -26,5 +26,13 @@ ...@@ -26,5 +26,13 @@
padding-left: 10.5px; padding-left: 10.5px;
color: rgba(207, 219, 229, .8); color: rgba(207, 219, 229, .8);
font-size: 15px; font-size: 15px;
/*img{
width: 100%;
}*/
}
.subtitle{
font-size: 14px;
color: #FFD667;
} }
} }
\ No newline at end of file
import React, { Component } from 'react';
import './index.scss'
import Container from './container'
import SingleAnswerQuestion from "@components/interactive-tutorial/single-answer-question"
import Program from "@components/interactive-tutorial/program"
import Project from './project'
import { getParam, http, getWXObject } from "@/utils"
import { Toast } from 'antd-mobile'
import { questionType, status } from './consts'
import Catalog from './catalog'
class InteractiveStudy extends Component {
singleIcon = 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/interactive_tutorial/study/single-answer-icon.png'
programIcon = 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/interactive_tutorial/study/program-icon.png'
state = {
options: [
'A. 程序向屏幕输出信息的过程,是人与计算机的单向沟通。',
'B. 程序向内部输入信息的过程。',
'C. 程序向内部输入信息的过程。',
],
img: 'https://julyedu-cdn.oss-cn-beijing.aliyuncs.com/weekend/bigdata/project/07.png',
page: 1,
schedule: {},
pageData: {},
processContent: [],
processStatus: status.startPractice,
isComplete: false,
}
componentDidMount() {
this.getSchedule().then(res => {
const {code, msg, data} = res.data
if (code === 200) {
this.setState({
schedule: data,
})
this.getPageContent(data.current_video_id)
} else {
this.showToast(msg)
}
})
}
getSchedule = () => {
return http.post(`${API.home}/m/it/study/schedule`, {
course_id: getParam('id'),
})
}
showToast = (msg, type = 'info') => {
Toast[type](msg, 2, null, false)
}
getPageContent = (videoId) => {
http.post(`${API.home}/m/it/study/syllabus?page=${this.state.page}`, {
course_id: getParam('id'),
video_id: videoId,
type: 1,
}).then(res => {
const {code, msg, data} = res.data
if (code === 200) {
this.setState({
pageData: data,
})
} else {
this.showToast(msg)
}
})
}
render() {
const {processStatus} = this.state
return (
<div id={'interactive-study'}>
<Catalog title={'Print()函数'}/>
<Container>
<span className={'subtitle'}>副标题</span>
</Container>
<Container>
<img
src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1590155695725&di=0a1cad792ef55dc43305ab904aae04fb&imgtype=0&src=http%3A%2F%2Fsearchfoto.ru%2Fimg%2FxyygpKbDS1y8pTjXUy83VS8rMS9fLSy3RL8mwz0yx9fcM0EtJ0S2PyCnOy8sOSTMOqQq38I23NHf0SHTNV0vMLbAutzUyNgCzMmwNzSGsomJbQzCjIDnHNgUMwNx8W1OIMNBoQz1DAA.jpg"
alt=""/>
</Container>
<Container user={'https://julyedu-img-public.oss-cn-beijing.aliyuncs.com/Public/Image/home/avatar_20191104.png'}
content={'Hi!初次见面,我叫小柒,是你在七月在线的课程导师。从现在开始,你就要跟着我一起学Python啦,请敲回车键继续课程。'}/>
<SingleAnswerQuestion user={this.singleIcon} topic={'请问,你会推荐哪个物品给用户C?'} options={this.state.options}
img={this.state.img}/>
<Program user={this.programIcon} code={"week = ['星期一', '星期二', '星期三']\nprint(123)"}/>
{/*<Project user={this.singleIcon}/>*/}
<div className="status-bar">
{/*<span className={'complete'}>已学完全部课时</span>*/}
<span className={'status'}>{processStatus}</span>
{/*<div className="free-trial-end">*/}
{/* <span>试学体验结束,389.1元学习全部课时</span>*/}
{/* <button className={'purchase'}>立即购买</button>*/}
{/*</div>*/}
</div>
</div>
);
}
}
export default InteractiveStudy;
\ No newline at end of file
#interactive-study {
position: relative;
min-height: 100%;
background-color: #252529;
padding-bottom: 49px;
padding-top: 20px;
& + .year19-index {
display: none;
}
.container:last-child {
margin-bottom: 0;
}
.status-bar {
$height: 49px;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: $height;
background: #3E3F47;
line-height: $height;
text-align: center;
color: #CFDBE5;
.complete {
color: rgba(207, 219, 229, .2);
font-size: 18px;
}
.status{
color: #CFDBE5;
font-size: 12px;
}
.free-trial-end {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 15px;
button{
width: 80px;
height: 30px;
-webkit-appearance: none;
border: none;
outline: 0;
background: #FA5C19;
font-size: 14px;
color: #fff;
}
}
}
}
\ No newline at end of file
...@@ -5,7 +5,8 @@ import AceEditor from 'react-ace' ...@@ -5,7 +5,8 @@ import AceEditor from 'react-ace'
import 'ace-builds/src-min-noconflict/theme-dracula' import 'ace-builds/src-min-noconflict/theme-dracula'
import 'ace-builds/src-min-noconflict/mode-python' import 'ace-builds/src-min-noconflict/mode-python'
import StatusBar from './status-bar' import StatusBar from './status-bar'
const {First, Normal} = StatusBar
const {First, Normal, Pass, Error, InputTip} = StatusBar
class Program extends Component { class Program extends Component {
editor = null editor = null
...@@ -20,7 +21,7 @@ class Program extends Component { ...@@ -20,7 +21,7 @@ class Program extends Component {
const contentWidth = content.clientWidth const contentWidth = content.clientWidth
const contentPaddingLeft = parseFloat(contentStyles.getPropertyValue('padding-left')) const contentPaddingLeft = parseFloat(contentStyles.getPropertyValue('padding-left'))
this.setState({ this.setState({
editorWidth: `${contentWidth - contentPaddingLeft}px` editorWidth: `${contentWidth - contentPaddingLeft}px`,
}) })
} }
...@@ -47,7 +48,7 @@ class Program extends Component { ...@@ -47,7 +48,7 @@ class Program extends Component {
height={'141px'} height={'141px'}
onLoad={this.onLoad} onLoad={this.onLoad}
/> />
<Normal/> <InputTip/>
</div> </div>
} }
/> />
......
.program{ .program {
background-color: #1f1f24; background-color: #1f1f24;
padding-top: 12px; padding-top: 12px;
.ace-dracula { .ace-dracula {
background: rgba(31, 31, 36, 1); background: rgba(31, 31, 36, 1);
......
...@@ -13,26 +13,49 @@ const Base = ({children, className}) => { ...@@ -13,26 +13,49 @@ const Base = ({children, className}) => {
const First = ({execute}) => { const First = ({execute}) => {
return <Base className={'first'}> return <Base className={'first'}>
<div className="hint">当前环境暂不支持编写程序,可前往PC端练习或点击按钮</div> <div className="tip">当前环境暂不支持编写程序,可前往PC端练习或点击按钮</div>
<button className={'btn'} onClick={execute}>运行并查看结果</button> <button className={'btn'} onClick={execute}>运行并查看结果</button>
</Base> </Base>
} }
const Normal = ({execute, checkAnswer}) => { const Normal = ({execute, checkAnswer, showAnswerButton = true}) => {
return <Base className={'normal'}> return <Base className={'normal'}>
<button className={'check-answer'} onClick={checkAnswer}>查看参考答案</button> {
showAnswerButton && <button className={'check-answer'} onClick={checkAnswer}>查看参考答案</button>
}
<button className={'btn'} onClick={execute}>运行</button> <button className={'btn'} onClick={execute}>运行</button>
</Base> </Base>
} }
const Pass = () => { const Pass = () => {
return <Base className={'pass'}> return <Base className={'pass'}>
<i className={'iconfont icondanseshixintubiao-3'}></i> <i className={'iconfont icondanseshixintubiao-5'}></i>
<span>运行通过</span> <span>运行通过</span>
</Base> </Base>
} }
const Error = ({showSkip = true}) => {
return <Base className={'error'}>
<div className="left">
<i className="iconfont icondanseshixintubiao-3"></i>
<span>7行出现错误</span>
{showSkip && <a href="javascript:void(0);">跳过本题</a>}
</div>
<button>查看答案</button>
</Base>
}
const InputTip = () => {
return <Base className={'input-tip'}>
<div className="tip">输入完毕后请点击确认</div>
<button>确认</button>
</Base>
}
export default { export default {
First, First,
Normal Normal,
Pass,
Error,
InputTip
}; };
\ No newline at end of file
...@@ -2,6 +2,7 @@ $primaryColor: rgba(0, 153, 255, .8); ...@@ -2,6 +2,7 @@ $primaryColor: rgba(0, 153, 255, .8);
.base-status-bar { .base-status-bar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
height: 44px; height: 44px;
padding: 8px 10px; padding: 8px 10px;
background: #2B2B33; background: #2B2B33;
...@@ -16,11 +17,12 @@ $primaryColor: rgba(0, 153, 255, .8); ...@@ -16,11 +17,12 @@ $primaryColor: rgba(0, 153, 255, .8);
border-radius: 4px; border-radius: 4px;
-webkit-appearance: none; -webkit-appearance: none;
outline: 0; outline: 0;
padding: 8px 12px;
} }
} }
.first { .first {
.hint { .tip {
width: 169px; width: 169px;
} }
...@@ -40,18 +42,55 @@ $primaryColor: rgba(0, 153, 255, .8); ...@@ -40,18 +42,55 @@ $primaryColor: rgba(0, 153, 255, .8);
color: $primaryColor; color: $primaryColor;
background-color: transparent; background-color: transparent;
} }
.btn {
padding-left: 12px;
padding-right: 12px;
}
} }
.pass{ .pass {
justify-content: flex-start; justify-content: flex-start;
align-content: center; align-items: center;
color: #74c27c; color: #74c27c;
.iconfont{ background: rgba(116, 193, 124, .3);
.iconfont {
font-size: 18px; font-size: 18px;
margin-right: 10px;
}
}
.only-execute {
justify-content: flex-end;
}
.error {
align-items: center;
.left {
color: #C24E55;
a {
color: #fff;
text-decoration: underline;
margin-left: 15px;
}
}
.iconfont {
font-size: 18px;
margin-right: 10px;
}
span {
font-size: 15px;
}
}
.input-tip{
.tip{
font-size: 12px;
color: #CFDBE5;
}
button{
border: 1px solid #09f;
background: transparent;
color: #09f;
} }
} }
\ No newline at end of file
import React, { Component } from 'react';
import Container from '../container'
import './index.scss'
class Project extends Component {
render() {
return (
<Container user={this.props.user}>
<div id={'project'}>
<table border={1}>
<thead>
<tr>
<th>项目资料</th>
<th>项目进度</th>
<th>项目成绩</th>
</tr>
</thead>
<tbody>
<tr>
<td className={'pc-tip'}>请前往PC端下载</td>
<td>
<span className={'pc-tip'}>请前往PC端提交</span><br/>
<span>2020-02-28截止</span>
</td>
<td>2020-XX-XX公布</td>
</tr>
</tbody>
</table>
</div>
</Container>
);
}
}
export default Project;
\ No newline at end of file
html,body{
min-height: 100%;
}
#project {
table {
width: 315px;
border: 1px solid #252529;
font-size: 11px;
color: #CFDBE5;
background: #2E2E33;
.pc-tip {
color: #09f;
}
td, th {
width: 99px;
height: 44px;
vertical-align: middle;
text-align: center;
}
}
thead {
th {
font-size: 15px;
color: #CFDBE6;
border-bottom: 1px solid #252529;
&:nth-child(2) {
border-left: 1px solid #252529;
border-right: 1px solid #252529;
}
}
}
tbody {
td {
&:nth-child(2) {
border-left: 1px solid #252529;
border-right: 1px solid #252529;
}
}
}
}
\ No newline at end of file
...@@ -332,7 +332,7 @@ export default [ ...@@ -332,7 +332,7 @@ export default [
}, },
{ {
path: '/interactive-study', path: '/interactive-tutorial',
component: loadable(() => import(/* webpackChunkName: 'interactive-study' */'@/components/interactive-study')) component: loadable(() => import(/* webpackChunkName: 'interactive-tutorial' */'@/components/interactive-tutorial'))
} }
] ]
...@@ -3,7 +3,7 @@ import { ...@@ -3,7 +3,7 @@ import {
differenceInDays, differenceInDays,
differenceInHours, differenceInHours,
differenceInMinutes, differenceInMinutes,
differenceInSeconds differenceInSeconds,
} from 'date-fns' } from 'date-fns'
...@@ -15,7 +15,7 @@ export const getParam = (key, str) => { ...@@ -15,7 +15,7 @@ export const getParam = (key, str) => {
} }
const html = content => ({ const html = content => ({
__html: htmlDecode(content) __html: htmlDecode(content),
}) })
const htmlDecode = content => { const htmlDecode = content => {
...@@ -93,7 +93,7 @@ const browser = (function () { ...@@ -93,7 +93,7 @@ const browser = (function () {
isIOS: /\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(ua), isIOS: /\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(ua),
isIPad: /iPad/i.test(ua), isIPad: /iPad/i.test(ua),
isAndroidApp: /Android/i.test(ua) && getParam('version'), isAndroidApp: /Android/i.test(ua) && getParam('version'),
isIOSApp: /iPhone/i.test(ua) && getParam('version') isIOSApp: /iPhone/i.test(ua) && getParam('version'),
} }
})() })()
...@@ -110,19 +110,20 @@ const dateCountDown = (later, earlier) => { ...@@ -110,19 +110,20 @@ const dateCountDown = (later, earlier) => {
d, d,
h, h,
m, m,
s s,
} }
} }
export { export {
default as http default as http,
} }
from './http' from './http'
export { export {
default as wxShare default as wxShare,
} }
from './wechat/share' from './wechat/share'
export { getWXObject } from './wechat/base'
export { export {
html, html,
initCaptcha, initCaptcha,
...@@ -130,9 +131,9 @@ export { ...@@ -130,9 +131,9 @@ export {
validateEmail, validateEmail,
browser, browser,
isLogin, isLogin,
dateCountDown dateCountDown,
} }
export { export {
default as SendMessageToApp default as SendMessageToApp,
} }
from './app' 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