Merge branch 'dev_aliyun' into develop

dev_cxt
cxt 5 years ago
commit b571e805ca

@ -1,4 +1,5 @@
class Admins::CustomersController < Admins::BaseController
# skip_before_action :check_sign
helper_method :current_partner
def index

@ -45,6 +45,16 @@ module GitHelper
content: content, author_name: username, author_email: mail)
end
# 添加目录
def git_add_folder(folder_path, author_name, author_email, message)
GitService.add_tree(file_path: folder_path, message: message, author_name: author_name, author_email: author_email)
end
# 删除文件
def git_delete_file(file_path, author_name, author_email, message)
GitService.delete_file(file_path: file_path, message: message, author_name: author_name, author_email: author_email)
end
# 版本库Fork功能
def project_fork(container, original_rep_path, username)
raise Educoder::TipException.new("fork源路径为空,fork失败!") if original_rep_path.blank?

@ -1,4 +1,5 @@
class PartnersController < ApplicationController
skip_before_action :check_sign
include Base::PaginateHelper
include Admins::RenderHelper

@ -18,13 +18,14 @@ class ShixunsController < ApplicationController
before_action :find_repo_name, only: [:repository, :commits, :file_content, :update_file, :shixun_exec, :copy,
:add_file, :jupyter_exec]
before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, :apply_public,
before_action :allowed, only: [:update, :close, :update_propaedeutics, :settings, :publish, :apply_public, :upload_git_folder,
:shixun_members_added, :change_manager, :collaborators_delete, :upload_git_file,
:cancel_apply_public, :cancel_publish, :add_collaborators, :add_file]
:cancel_apply_public, :cancel_publish, :add_collaborators, :add_file, :delete_git_file]
before_action :portion_allowed, only: [:copy]
before_action :special_allowed, only: [:send_to_course, :search_user_courses]
before_action :shixun_marker, only: [:new, :create]
skip_before_action :check_sign, only: [:download_file]
## 获取课程列表
def index
@ -892,7 +893,22 @@ class ShixunsController < ApplicationController
content = upload_file.tempfile.read
author_name = current_user.real_name
author_email = current_user.git_mail
update_file_content(content, @repo_path, author_email, author_name, "upload file by browser")
update_file_content(content, @repo_path, @path, author_email, author_name, "upload file by browser")
render_ok
end
# 上传目录
def upload_git_folder
author_name = current_user.real_name
author_email = current_user.git_mail
git_add_folder(@path, author_name, author_email, "upload folder by browser")
render_ok
end
def delete_git_file
author_name = current_user.real_name
author_email = current_user.git_mail
git_delete_file(@path, author_name, author_email, "delete filer by browser")
render_ok
end

@ -2,6 +2,7 @@ class UsersController < ApplicationController
before_action :load_user, only: [:show, :homepage_info]
before_action :check_user_exist, only: [:show, :homepage_info]
skip_before_action :check_sign, only: [:attachment_show]
# 检查是否更新
def system_update

@ -6,7 +6,7 @@ class GitService
class << self
['add_repository', 'fork_repository', 'delete_repository', 'file_tree', 'update_file', 'file_content', 'commits'].each do |method|
['add_repository', 'fork_repository', 'delete_repository', 'file_tree', 'update_file', 'file_content', 'commits', 'add_tree', 'delete_file'].each do |method|
define_method method do |params|
post(method, params)
end

@ -8,7 +8,8 @@ module JupyterService
uri = "#{shixun_tomcat}/bridge/jupyter/get"
tpiID = "tpm#{shixun.id}"
mount = shixun.data_sets.present?
params = {tpiID: tpiID, identifier: shixun.identifier, needMount: mount, gitUrl: '',
gitUrl = "#{edu_setting('git_address_domain')}/#{shixun.repo_path}"
params = {tpiID: tpiID, identifier: shixun.identifier, needMount: mount, gitUrl: gitUrl,
:containers => "#{Base64.urlsafe_encode64(shixun_container_limit(shixun))}"}
logger.info "test_juypter: uri->#{uri}, params->#{params}"

@ -280,6 +280,8 @@ Rails.application.routes.draw do
post :commits
post :file_content
post :upload_git_file
post :upload_git_folder
delete :delete_git_file
post :update_file
post :close
post :add_file

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 785 B

@ -83,7 +83,7 @@ export function initAxiosInterceptors(props) {
//proxy="http://47.96.87.25:48080"
proxy="https://pre-newweb.educoder.net"
proxy="https://test-newweb.educoder.net"
// proxy="https://test-jupyterweb.educoder.net"
proxy="https://test-jupyterweb.educoder.net"
//proxy="http://192.168.2.63:3001"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
@ -123,7 +123,10 @@ export function initAxiosInterceptors(props) {
}
}
if(`${config[0]}`!=`true`){
let timestamp = Date.parse(new Date())/1000;
if (window.location.port === "3007") {
// let timestamp=railsgettimes(proxy);
console.log(timestamp)
railsgettimes(`${proxy}/api/main/first_stamp.json`);
let newopens=md5(opens+timestamp)
config.url = `${proxy}${url}`;

@ -1,4 +1,8 @@
import React from "react";
import md5 from 'md5';
import {Input} from "antd";
const { Search } = Input;
const $ = window.$;
const isDev = window.location.port == 3007;
export const TEST_HOST = "https://test-newweb.educoder.net"
@ -150,3 +154,15 @@ export function htmlEncode(str) {
s = s.replace(/\"/g, "&quot;");
return s;
}
export function publicSearchs(Placeholder,onSearch,onInputs,onChanges,loadings) {
return(<Search
placeholder= { Placeholder || "请输入内容进行搜索" }
onSearch={onSearch}
// value={searchValue}
onInput={onInputs}
onChange={onChanges}
loading={loadings||false}
allowClear={true}
></Search>)
}

@ -2,7 +2,7 @@
// export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil';
export { getImageUrl as getImageUrl, getUrl as getUrl, getRandomcode as getRandomcode,getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
export { getImageUrl as getImageUrl, getUrl as getUrl, publicSearchs as publicSearchs,getRandomcode as getRandomcode,getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl,getUploadActionUrltwo as getUploadActionUrltwo ,getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
, getTaskUrlById as getTaskUrlById, TEST_HOST ,htmlEncode as htmlEncode } from './UrlTool';
export { default as queryString } from './UrlTool2';

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-12-16 15:50:45
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 15:07:11
* @LastEditTime : 2019-12-31 13:59:02
*/
import Quill from "quill";
@ -50,6 +50,7 @@ export default class ImageBlot extends BlockEmbed {
return node;
}
// 获取节点值
static value (node) {
return {

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-12-18 08:49:30
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 16:49:25
* @LastEditTime : 2019-12-31 15:11:37
*/
import './index.scss';
import 'quill/dist/quill.core.css'; // 核心样式
@ -18,10 +18,18 @@ import deepEqual from './deepEqual.js'
import { fetchUploadImage } from '../../services/ojService.js';
import { getImageUrl } from 'educoder'
import ImageBlot from './ImageBlot';
const Size = Quill.import('attributors/style/size');
const Font = Quill.import('formats/font');
// const Color = Quill.import('attributes/style/color');
Size.whitelist = ['12px', '14px', '16px', '18px', '20px', false];
Font.whitelist = ['SimSun', 'SimHei','Microsoft-YaHei','KaiTi','FangSong','Arial','Times-New-Roman','sans-serif'];
window.Quill = Quill;
window.katex = katex;
Quill.register(ImageBlot);
Quill.register(Size);
Quill.register(Font, true);
// Quill.register(Color);
function QuillForEditor ({
placeholder,
@ -38,15 +46,16 @@ function QuillForEditor ({
}) {
// toolbar 默认值
const defaultConfig = [
['bold', 'italic', 'underline'],
[{align: []}, {list: 'ordered'}, {list: 'bullet'}], // 列表
[{script: 'sub'}, {script: 'super'}],
[{ 'color': [] }, { 'background': [] }],
[{header: [1,2,3,4,5,false]}],
['blockquote', 'code-block'],
['link', 'image', 'video'],
['formula'],
['clean']
'bold', 'italic', 'underline',
{size: ['12px', '14px', '16px', '18px', '20px']},
{align: []}, {list: 'ordered'}, {list: 'bullet'}, // 列表
{script: 'sub'}, {script: 'super'},
{ 'color': [] }, { 'background': [] },
{header: [1,2,3,4,5,false]},
'blockquote', 'code-block',
'link', 'image', 'video',
'formula',
'clean'
];
const editorRef = useRef(null);

@ -7,4 +7,107 @@
cursor: pointer;
}
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
content: '12px';
font-size: 12px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
content: '14px';
font-size: 14px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
content: '16px';
font-size: 16px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
content: '18px';
font-size: 18px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
content: '20px';
font-size: 20px;
}
//
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: '14px';
font-size: 14px;
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
content: "宋体";
font-family: "SimSun";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
content: "黑体";
font-family: "SimHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
content: "微软雅黑";
font-family: "Microsoft YaHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
content: "楷体";
font-family: "KaiTi";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
content: "仿宋";
font-family: "FangSong";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
content: "Arial";
font-family: "Arial";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
content: "Times New Roman";
font-family: "Times New Roman";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
content: "sans-serif";
font-family: "sans-serif";
}
.ql-font-SimSun {
font-family: "SimSun";
}
.ql-font-SimHei {
font-family: "SimHei";
}
.ql-font-Microsoft-YaHei {
font-family: "Microsoft YaHei";
}
.ql-font-KaiTi {
font-family: "KaiTi";
}
.ql-font-FangSong {
font-family: "FangSong";
}
.ql-font-Arial {
font-family: "Arial";
}
.ql-font-Times-New-Roman {
font-family: "Times New Roman";
}
.ql-font-sans-serif {
font-family: "sans-serif";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "微软雅黑";
font-family: "Microsoft YaHei";
}
}

@ -3,8 +3,8 @@
* @Author: tangjiang
* @Github:
* @Date: 2019-11-20 23:10:48
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-06 15:53:27
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-02 14:57:02
*/
const CONST = {
jcLabel: {
@ -12,9 +12,11 @@ const CONST = {
language: '编程语言',
description: '描述',
difficult: '难易度',
category: '分类',
category: '课程',
openOrNot: '公开程序',
timeLimit: '时间限制'
timeLimit: '时间限制',
knowledge: '知识点',
sub_discipline_id: '课程'
},
fontSetting: {
title: '代码格式',

@ -253,22 +253,22 @@ class Fileslistitem extends Component{
{discussMessage.is_publish===false?<CoursesListType typelist={["未发布"]} typesylename={""}/>:""}
{this.props.isAdmin?
<span className={"fr mr10 mt2"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<span className={"fr mt2"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
<a className="btn colorblue fontweight400"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
</span>:""}
{this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login?
<span className={"fr mr10 mt2"} onClick={(event)=>this.eventStop(event)}>
<span className={"fr mt2"} onClick={(event)=>this.eventStop(event)}>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
<a className="btn colorblue fontweight400"
onClick={()=>this.settingList()}>设置</a>
</WordsBtn>
<WordsBtn style="blue" className="colorblue font-16 mr20 fr">
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
<a className="btn colorblue fontweight400"
onClick={()=>this.onDelete(discussMessage.id)}>删除</a>
</WordsBtn>
@ -329,7 +329,7 @@ class Fileslistitem extends Component{
{ discussMessage.publish_time===null?"":discussMessage.is_publish===true?moment(discussMessage.publish_time).fromNow():moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm')}
</span>
</span>
{discussMessage&&discussMessage.category_name===null?"":this.props.child===false?<div className="color-grey9 task-hide fr mr60" title={discussMessage&&discussMessage.category_name}
{discussMessage&&discussMessage.category_name===null?"":this.props.child===false?<div className="color-grey9 task-hide fr mr30" title={discussMessage&&discussMessage.category_name}
style={{"max-width":"268px"}}>所属目录{discussMessage&&discussMessage.category_name}
</div>:""}
</p>

@ -230,7 +230,8 @@ class Fileslists extends Component{
filesId:list.id,
name:list.name,
course_is_public:result.data.data.course_is_public,
isSpin:false
isSpin:false,
page:page
})
}
}
@ -423,7 +424,7 @@ class Fileslists extends Component{
onPressEnter = () => {
let {searchValue}=this.state;
let{pagesize,page,tagname,sort,sorttype,coursesecondcategoryid}=this.state;
this.getfileslist(pagesize,page,tagname,searchValue,sort,sorttype,coursesecondcategoryid);
this.getfileslist(pagesize,1,tagname,searchValue,sort,sorttype,coursesecondcategoryid);
}
onInputSearchChange = (e) => {
@ -850,6 +851,7 @@ class Fileslists extends Component{
searchValue={ searchValue }
// searchtype={this.props.isAdmin||this.props.isStudent ?true:false}
onInputSearchChange={this.onInputSearchChange}
allowClearonChange={this.onInputSearchChange}
firstRowRight={
<React.Fragment>
{/*{this.props.isAdmin()?parseInt(this.props.match.params.main_id)===parseInt(this.props.coursesids)?<WordsBtn style="blue" onClick={()=>this.addDir()} className={"mr30 font-16"}>新建目录</WordsBtn>:"":""}*/}

@ -346,6 +346,7 @@ class Boards extends Component{
title={boardName || "帖子列表"}
searchValue={ searchValue }
onInputSearchChange={this.onInputSearchChange}
allowClearonChange={this.onInputSearchChange}
showSearchInput={messages.length >= 10}
searchPlaceholder={ '请输入帖子名称进行搜索' }
firstRowRight={

@ -1,28 +1,17 @@
import React,{Component} from "react";
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip,Spin, Pagination} from "antd";
import {Link} from 'react-router-dom';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import {WordsBtn, ConditionToolTip, queryString, getImageUrl, on, off, NoneData, sortDirections} from 'educoder';
import {WordsBtn, ConditionToolTip, queryString, publicSearchs, on, off, NoneData, sortDirections} from 'educoder';
import axios from 'axios';
import Modals from '../../modals/Modals';
import CoursesListType from '../coursesPublic/CoursesListType';
import HomeworkModal from "../coursesPublic/HomeworkModal";
import CheckAllGroup from '../common/button/CheckAllGroup'
import moment from 'moment';
import CheckCodeModal from '../coursesPublic/modal/CheckCodeModal'
import '../css/Courses.css'
import WorkDetailPageHeader from './common/WorkDetailPageHeader'
import '../css/Courses.css';
import PublishRightnow from './PublishRightnow'
import ModulationModal from "../coursesPublic/ModulationModal";
import AccessoryModal from "../coursesPublic/AccessoryModal";
import LeaderIcon from './common/LeaderIcon'
const { Option} = Select;
const CheckboxGroup = Checkbox.Group;
const confirm = Modal.confirm;
let GraduationTasksnewtype=true;
const $ = window.$;
const Search = Input.Search;
const RadioGroup = Radio.Group;
function renderScore(score, content) {
let color = '#747A7F'
@ -414,6 +403,8 @@ class CommonWorkList extends Component{
left_time: {},
category: {},
b_order: 'desc',
searchtypes:false,
loadingstate:false
}
}
onTablePagination = (page) => {
@ -423,10 +414,28 @@ class CommonWorkList extends Component{
}
onSearchValue = (val) => {
if (val === ""||val===undefined) {
this.setState({
search: undefined,
searchtypes:false
})
}else{
this.setState({
searchtypes:true,
loadingstate:true
})
}
this.fetchList()
}
onSearchValueInput = (e) => {
this.setState({search: e.target.value})
if (e.target.value === ""||e.target.value===undefined) {
this.setState({
search: undefined,
})
} else {
this.setState({search: e.target.value})
}
}
componentDidMount() {
@ -476,7 +485,8 @@ class CommonWorkList extends Component{
if (response.data) {
this.setState({
...response.data,
isSpin:false
isSpin:false,
loadingstate:false
})
this.props.initWorkDetailCommonState && this.props.initWorkDetailCommonState( Object.assign({...response.data}, {
@ -486,7 +496,8 @@ class CommonWorkList extends Component{
}).catch((error)=>{
console.log(error)
this.setState({
isSpin:false
isSpin:false,
loadingstate:false
})
})
@ -789,13 +800,14 @@ class CommonWorkList extends Component{
{/* value={search} */}
<div className="fr search-new mr8" style={{marginBottom:'1px'}}>
<Search
placeholder="请输入姓名或学号搜索"
id="subject_search_input"
onInput={this.onSearchValueInput}
onSearch={this.onSearchValue}
autoComplete="off"
></Search>
{/*<Search*/}
{/* placeholder="请输入姓名或学号搜索1"*/}
{/* id="subject_search_input"*/}
{/* onInput={this.onSearchValueInput}*/}
{/* onSearch={this.onSearchValue}*/}
{/* autoComplete="off"*/}
{/*></Search>*/}
{publicSearchs("请输入姓名或学号搜索",this.onSearchValue,this.onSearchValueInput,this.onSearchValueInput)}
</div>
</ul> }
@ -843,9 +855,9 @@ class CommonWorkList extends Component{
<div className={"justify break_full_word new_li edu-back-white course_table_wrap"} style={{minHeight:"480px", marginBottom: '30px'}}>
<style>{`
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;}
}
// .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
// top: 72%;}
// }
.singleLine tr.ant-table-row {
background: #f1f9ff;
}
@ -859,22 +871,26 @@ class CommonWorkList extends Component{
<div id="forum_list" className="forum_table">
<div className="mh650 edu-back-white">
<NoneData></NoneData>
<NoneData
{...this.props}
{...this.state}
></NoneData>
</div>
</div>
</Spin>
:
<React.Fragment>
<Table
className="stageTable"
dataSource={student_works}
columns={columns}
showQuickJumper
pagination={false}
onChange={this.table1handleChange}
loading={loadingstate}
/>
<Spin tip="正在加载..." spinning={loadingstate}>
<Table
className="stageTable"
dataSource={student_works}
columns={columns}
showQuickJumper
pagination={false}
onChange={this.table1handleChange}
// loading={loadingstate}
/>
</Spin>
</React.Fragment>
}

@ -1,28 +1,22 @@
import React,{ Component } from "react";
import { Input,Checkbox,Menu,Pagination,Spin} from "antd";
import CourseLayoutcomponent from '../common/CourseLayoutComponent';
import UseBank from './UseBank'
import '../css/members.css'
import '../css/busyWork.css'
import CoursesListType from '../coursesPublic/CoursesListType'
import CommonWorkItem from './CommonWorkItem'
import PublishRightnow from './PublishRightnow'
import ConnectProject from './ConnectProject'
import { WordsBtn, on, off } from 'educoder'
import Modals from '../../modals/Modals'
import NoneData from "../coursesPublic/NoneData"
import Titlesearchsection from '../common/titleSearch/TitleSearchSection';
import { RouteHOC } from './common'
import axios from 'axios';
import _ from 'lodash'
const Search = Input.Search;
const map={1:"普通作业",2:"",3:"分组作业"}
const COMMON_WORK = 1
// const Search = Input.Search;
// const map={1:"普通作业",2:"",3:"分组作业"}
// const COMMON_WORK = 1
// const COMMON_WORK = 2
class commonWork extends Component{
constructor(props){
@ -47,13 +41,12 @@ class commonWork extends Component{
inputStudent=(e)=>{
this.setState({
search:e.target.value,
page:1
})
}
//搜索查询
searchStudent=()=>{
let {page,search,order}=this.state;
this.getList(page,search,order);
this.getList(1,search,order);
}
openConnectionProject = (work) => {
this.refs['connectProject'].openConnectionProject(work)
@ -134,11 +127,14 @@ class commonWork extends Component{
mainList:result.data,
totalCount:result.data.task_count,
isSpin:false,
page:page,
...result.data
})
}
}).catch((error)=>{
console.log(error);
this.setState({
isSpin:false
})
})
}
//筛选条件
@ -325,7 +321,7 @@ class commonWork extends Component{
console.log(error)
})
}
render(){
let {
@ -396,7 +392,7 @@ class commonWork extends Component{
// searchtype={this.props.isAdmin||this.props.isStudent ?true:false}
onInputSearchChange={this.inputStudent}
onPressEnter={this.searchStudent}
allowClearonChange={this.inputStudent}
firstRowRight={
<React.Fragment>
{ isAdmin && <WordsBtn style="blue" className="fr" onClick={()=>this.createCommonWork(1)}>新建</WordsBtn>}

@ -1,8 +1,5 @@
import React,{ Component } from "react";
import { Input } from "antd";
const Search = Input.Search;
import {publicSearchs} from 'educoder';
class Titlesearchsection extends Component{
constructor(props){
super(props);
@ -14,7 +11,7 @@ class Titlesearchsection extends Component{
render(){
let { addGroup } = this.state;
const { firstRowRight, secondRowLeft,firstRowMid, secondRowBotton,thirdRow, title, onInputSearchChange
, searchValue, onPressEnter, searchPlaceholder, showSearchInput } = this.props;
, searchValue, onPressEnter, searchPlaceholder, allowClearonChange } = this.props;
return(
<React.Fragment>
<style>{`
@ -79,12 +76,15 @@ class Titlesearchsection extends Component{
{/* (searchValue || showSearchInput) && */}
{ <div className="fr mt16 mb16 searchView" >
<Search
onSearch={onPressEnter}
value={searchValue}
placeholder= { searchPlaceholder || "请输入姓名进行搜索" }
onInput={onInputSearchChange}
></Search>
{publicSearchs(searchPlaceholder || "请输入姓名进行搜索",onPressEnter,onInputSearchChange,allowClearonChange)}
{/*<Search */}
{/* onSearch={onPressEnter}*/}
{/* // value={searchValue}*/}
{/* placeholder= { searchPlaceholder || "请输入姓名进行搜索" }*/}
{/* onInput={onInputSearchChange}*/}
{/* onChange={allowClearonChange}*/}
{/* allowClear={true}*/}
{/*></Search>*/}
</div> }
{secondRowBotton}

@ -6,7 +6,8 @@ class NoneData extends Component{
super(props)
}
render(){
const { style } = this.props;
const { style,searchtypes } = this.props;
return(
<div className="edu-tab-con-box clearfix edu-txt-center" style={ style || { width:"100%" }}>
<style>
@ -23,7 +24,7 @@ class NoneData extends Component{
`}
</style>
<img className="edu-nodata-img mb20" src={getUrl("/images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb20">暂时还没有相关数据哦</p>
<p className="edu-nodata-p mb20">{searchtypes===true?"抱歉没有您要搜索的内容,请换个词语试试看":"暂时还没有相关数据哦!"}</p>
</div>
)
}

@ -106,12 +106,11 @@ class Selectsetting extends Component{
savecouseShixunModal=()=>{
let {fileList,is_public,description,datatime,Radiovalue}=this.state;
let newfileList=[];
if(fileList!=undefined&&fileList.length>0){
for(var list of fileList){
fileList.map((list,key)=>{
newfileList.push(list.response.id)
}
})
}

@ -132,9 +132,9 @@ class Sendresource extends Component{
let newfileList=[];
if(fileList!=undefined&&fileList.length>0){
for(var list of fileList){
fileList.map((list,key)=>{
newfileList.push(list.response.id)
}
})
}

@ -1,11 +1,10 @@
import React,{ Component } from "react";
import { Input,Checkbox,Table, Pagination, Modal,Menu, Tooltip,Spin } from "antd";
import CourseLayoutcomponent from '../common/CourseLayoutComponent';
import {Checkbox, Pagination,Menu,Spin } from "antd";
import ExerciseListItem from './ExerciseListItem'
import axios from 'axios';
import Modals from '../../modals/Modals';
import '../css/members.css'
import { WordsBtn,on, off, trigger } from 'educoder'
import { WordsBtn,on, publicSearchs } from 'educoder'
import '../css/busyWork.css'
import _ from 'lodash';
import moment from 'moment'
@ -14,8 +13,6 @@ import ImmediatelyPublish from "../poll/pollPublicBtn/ImmediatelyPublish";
import ImmediatelyEnd from "../poll/pollPublicBtn/ImmediatelyEnd";
import NoneData from "../coursesPublic/NoneData";
import HomeworkModal from "../coursesPublic/HomeworkModal";
const Search = Input.Search;
class Exercise extends Component{
constructor(props){
@ -93,17 +90,20 @@ class Exercise extends Component{
exercises:result.data.exercises,
checkAllValue:false,
checkBoxValues:[],
isSpin:false
isSpin:false,
page:page
})
}).catch((error)=>{
console.log(error);
this.setState({
isSpin:false,
})
})
}
inputStudent=(e)=>{
this.setState({
StudentList_value:e.target.value
StudentList_value:e.target.value,
})
}
// 搜索
@ -505,12 +505,13 @@ class Exercise extends Component{
<span>未发布{exercises_counts && exercises_counts.exercises_unpublish_counts}</span>
</p>
<div className="fr mt16 mb16 searchView">
<Search
value={StudentList_value}
placeholder="请输入名称进行搜索"
onInput={this.inputStudent}
onSearch={this.searchInfo}
></Search>
{publicSearchs("请输入名称进行搜索",this.searchInfo,this.inputStudent,this.inputStudent)}
{/*<Search*/}
{/* value={StudentList_value}*/}
{/* placeholder="请输入名称进行搜索"*/}
{/* onInput={this.inputStudent}*/}
{/* onSearch={this.searchInfo}*/}
{/*></Search>*/}
</div>
</div>
<div className="task_menu_ul pl30 pr30">

@ -1,7 +1,6 @@
import React,{ Component } from "react";
import { Input, Checkbox, Menu,Pagination,Spin} from "antd";
import { Checkbox, Menu,Pagination,Spin} from "antd";
import {Link} from 'react-router-dom';
import CourseLayoutcomponent from '../../common/CourseLayoutComponent';
import Titlesearchsection from '../../common/titleSearch/TitleSearchSection';
import HomeworkModal from "../../coursesPublic/HomeworkModal";
import { WordsBtn } from 'educoder';
@ -10,7 +9,6 @@ import moment from 'moment';
import GraduateTaskItem from './GraduateTaskItem';
import TaskPublishModal from "./TaskPublishModal";
import Modals from '../../../modals/Modals';
import UseBank from "../../busyWork/UseBank";
import '../../css/members.css';
import '../style.css';
import NoneData from "../../coursesPublic/NoneData";
@ -65,7 +63,9 @@ class GraduationTasks extends Component{
})
}
}).catch(function (error) {
console.log(error);
this.setState({
isSpin:false
})
});
}
@ -286,7 +286,7 @@ class GraduationTasks extends Component{
onInputSearchChange = (e) => {
this.setState({
searchValue:e.target.value
searchValue:e.target.value,
})
if (this.timeoutHandler) {
@ -405,7 +405,8 @@ class GraduationTasks extends Component{
let {page,order}=this.state;
this.setState({
search:value
search:value,
isSpin:true
})
this.fetchAll(value,page,order);
@ -662,6 +663,7 @@ class GraduationTasks extends Component{
title="毕设任务"
searchValue={searchValue}
onInputSearchChange={this.onInputSearchChange}
allowClearonChange={this.onInputSearchChange}
firstRowRight={
<React.Fragment>
{/*{this.props.isAdmin() ?<WordsBtn style="blue" className="mr30" onClick={() => this.addDir()}>题库选用</WordsBtn>:""}*/}

@ -1,7 +1,6 @@
import React,{ Component } from "react";
import {Checkbox, Menu, Pagination,Spin} from "antd";
import CourseLayoutcomponent from '../../common/CourseLayoutComponent'
import Titlesearchsection from '../../common/titleSearch/TitleSearchSection'
import DownloadMessageysl from "../../../modals/DownloadMessageysl";
@ -9,7 +8,6 @@ import { WordsBtn ,getRandomcode} from 'educoder'
import NoneData from '../../coursesPublic/NoneData'
import Modals from "../../../modals/Modals"
import axios from 'axios'
import UseBank from '../../busyWork/UseBank'
import _ from 'lodash'
@ -85,12 +83,15 @@ class Boards extends Component{
topicList:response.data.graduation_topic,
totalCount:response.data.graduation_topic_count,
course_public:response.data.course_public,
isSpin:false
isSpin:false,
page:page
})
}
})
.catch(function (error) {
console.log(error);
this.setState({
isSpin:false
})
});
}
componentDidMount = () => {
@ -117,10 +118,11 @@ class Boards extends Component{
onInputSearchChange = (e) => {
this.setState({
searchValue:e.target.value
searchValue:e.target.value,
})
}
// 全选or反选
onCheckAll = (e) => {
this.setState({
@ -408,6 +410,7 @@ onBoardsNew=()=>{
title="毕设选题"
searchValue={ searchValue }
onInputSearchChange={this.onInputSearchChange}
allowClearonChange={this.onInputSearchChange}
firstRowRight=
{ isAdmin ?
(<React.Fragment>

@ -136,6 +136,7 @@ function CourseGroupList(props) {
title={"分班列表"}
searchValue={ searchValue }
onInputSearchChange={onInputSearchChange}
allowClearonChange={onInputSearchChange}
showSearchInput={total_count >= 10}
searchPlaceholder={ '请输入分班名称进行搜索' }
firstRowRight={

@ -1,6 +1,6 @@
import React,{ Component } from "react";
import { Input,Checkbox,Table, Pagination, Modal,Menu, Tooltip ,Spin} from "antd";
import {WordsBtn, on, off, trigger } from 'educoder';
import {Checkbox, Pagination,Menu ,Spin} from "antd";
import {WordsBtn, on, off, publicSearchs } from 'educoder';
import HomeworkModal from "../coursesPublic/HomeworkModal";
import AddcoursesNav from "../coursesPublic/AddcoursesNav";
import ImmediatelyPublish from './pollPublicBtn/ImmediatelyPublish';
@ -15,8 +15,6 @@ import Modals from '../../modals/Modals';
import axios from 'axios';
import moment from 'moment';
const Search = Input.Search;
class Poll extends Component{
constructor(props){
@ -66,7 +64,7 @@ class Poll extends Component{
inputStudent=(e)=>{
this.setState({
StudentList_value:e.target.value
StudentList_value:e.target.value,
})
}
@ -125,7 +123,8 @@ class Poll extends Component{
course_types:result.data.course_types,
polls_counts:result.data.polls_counts,
isSpin:false,
checkBoxValues: bank_checkValue ? bank_checkValue : []
checkBoxValues: bank_checkValue ? bank_checkValue : [],
page:page
})
}
}).catch((error)=>{
@ -524,12 +523,13 @@ class Poll extends Component{
<span>未发布{polls_counts && polls_counts.polls_unpublish_counts}</span>
</p>
<div className="fr mt16 mb16 searchView">
<Search
value={StudentList_value}
placeholder="请输入名称进行搜索"
onInput={this.inputStudent}
onSearch={this.searchInfo}
></Search>
{publicSearchs("请输入名称进行搜索",this.searchInfo,this.inputStudent,this.inputStudent)}
{/*<Search*/}
{/* value={StudentList_value}*/}
{/* placeholder="请输入名称进行搜索"*/}
{/* onInput={this.inputStudent}*/}
{/* onSearch={this.searchInfo}*/}
{/*></Search>*/}
</div>
</div>
<div className="task_menu_ul pl30 pr30">

@ -1,6 +1,6 @@
import React, {Component} from "react";
import CoursesListType from '../coursesPublic/CoursesListType';
import {WordsBtn, ActionBtn, sortDirections} from 'educoder';
import {WordsBtn, publicSearchs, sortDirections} from 'educoder';
import {
Form,
Select,
@ -65,6 +65,7 @@ class Listofworksstudentone extends Component {
//关卡得分final_score
this.state = {
searchtypes:false,
jobsettingsdata: undefined,
endTime: "2018/11/10 17:10:00",
type: "day",
@ -2588,6 +2589,7 @@ class Listofworksstudentone extends Component {
challenges_count: result.data.challenges_count,
homework_status: result.data.homework_status,
answer_open_evaluation:result.data.answer_open_evaluation,
page:page
});
allow_lates=result.data.allow_late;
answer_open_evaluation=result.data.answer_open_evaluation;
@ -2959,10 +2961,9 @@ class Listofworksstudentone extends Component {
}
//搜索学生 文字输入
inputSearchValuest = (e) => {
// console.log(e.target.value)
if (e.target.value === "") {
if (e.target.value === ""||e.target.value===undefined) {
this.setState({
searchtext: undefined
searchtext: undefined,
})
} else {
this.setState({
@ -2983,8 +2984,9 @@ class Listofworksstudentone extends Component {
loadingstate: true,
page: 1,
limit: 20,
searchtypes:true
})
this.Startsortingt(this.state.orders, this.state.course_groupyslstwo, this.state.checkedValuesineinfo, value, 1, 20, this.state.myorders);
this.Startsortingt(this.state.orders, this.state.course_groupyslstwo, this.state.checkedValuesineinfo, value, 1, 20, this.state.myorders);
// console.log(value)
@ -3576,12 +3578,18 @@ class Listofworksstudentone extends Component {
</div>:
homework_status && homework_status.length === 0 ?
<div className="edu-back-white">
<NoneData></NoneData>
<NoneData
{...this.state}
{...this.props}
/>
</div>
:
homework_status && homework_status.length > 0 && homework_status[0] === "未发布" ?
<div className="edu-back-white">
<NoneData></NoneData>
<NoneData
{...this.state}
{...this.props}
/>
</div>
:
<div className={"educontent "}>
@ -3664,15 +3672,16 @@ class Listofworksstudentone extends Component {
{/*}*/}
{/*</span>}*/}
<span className="search-newyslw fr ml20">
<Search
placeholder="请输入姓名或学号搜索"
id="subject_search_input"
autoComplete="off"
value={searchtext}
onKeyUp={(e) => this.onSearchKeywordKeyUpt(e)}
onInput={this.inputSearchValuest}
onSearch={this.searchValuest}
></Search>
{/*<Search*/}
{/* placeholder="请输入姓名或学号搜索"*/}
{/* id="subject_search_input"*/}
{/* autoComplete="off"*/}
{/* value={searchtext}*/}
{/* // onKeyUp={(e) => this.onSearchKeywordKeyUpt(e)}*/}
{/* onInput={this.inputSearchValuest}*/}
{/* onSearch={this.searchValuest}*/}
{/*></Search>*/}
{publicSearchs("请输入姓名或学号搜索",this.searchValuest,this.inputSearchValuest,this.inputSearchValuest)}
</span>
</div>
<span className="fl mr10 color-grey-8 ">作品状态</span>
@ -3760,7 +3769,7 @@ class Listofworksstudentone extends Component {
<div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
<p className="edu-nodata-p mb30">{this.state.searchtypes===false?"暂时还没有相关数据哦!":"抱歉没有您要搜索的内容,请换个词语试试看"}</p>
</div>
</div>
@ -3769,9 +3778,9 @@ class Listofworksstudentone extends Component {
<div className={"justify break_full_word new_li "} style={{minHeight: "480px"}}>
<style>{`
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;}
}
// .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
// top: 72%;
// }
.edu-table thead th,.edu-table tbody tr:last-child td{
border-bottom: none!important;
height: 58px;
@ -3787,13 +3796,16 @@ class Listofworksstudentone extends Component {
}
`}</style>
<div className="edu-table edu-back-white ant-tables ysltableo table1">
{datajs === undefined ? "" : <Table
dataSource={datajs}
columns={columns}
pagination={false}
onChange={this.table1handleChange}
loading={loadingstate}
/>}
<Spin tip="正在加载..." spinning={loadingstate}>
{datajs === undefined ? "" : <Table
dataSource={datajs}
columns={columns}
pagination={false}
onChange={this.table1handleChange}
loading={false}
/>}
</Spin>
</div>
</div>
}
@ -3898,12 +3910,18 @@ class Listofworksstudentone extends Component {
{
homework_status && homework_status.length && homework_status.length === 0 ?
<div className=" clearfix edu-back-white" style={{margin: "auto", minWidth: "1200px"}}>
<NoneData></NoneData>
<NoneData
{...this.state}
{...this.props}
/>
</div>
:
homework_status && homework_status.length > 0 && homework_status && homework_status[0] === "未发布" ?
<div className=" clearfix edu-back-white " style={{margin: "auto", minWidth: "1200px"}}>
<NoneData></NoneData>
<NoneData
{...this.state}
{...this.props}
/>
</div>
:
@ -4029,7 +4047,7 @@ class Listofworksstudentone extends Component {
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
<p className="edu-nodata-p mb30">{this.state.searchtypes===false?"暂时还没有相关数据哦!":"抱歉没有您要搜索的内容,请换个词语试试看"}</p>
</div>
</div>
@ -4069,12 +4087,18 @@ class Listofworksstudentone extends Component {
{
homework_status && homework_status.length === 0 ?
<div className=" clearfix edu-back-white" style={{margin: "auto", minWidth: "1200px"}}>
<NoneData></NoneData>
<NoneData
{...this.state}
{...this.props}
/>
</div>
:
homework_status && homework_status.length > 0 && homework_status && homework_status[0] === "未发布" ?
<div className=" clearfix edu-back-white" style={{margin: "auto", minWidth: "1200px"}}>
<NoneData></NoneData>
<NoneData
{...this.state}
{...this.props}
/>
</div>
:
<div className={"educontent mb20"}>
@ -4226,9 +4250,9 @@ class Listofworksstudentone extends Component {
<div className={"justify break_full_word new_li"}
style={{minHeight: "480px"}}>
<style>{`
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;}
}
// .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
// top: 72%;
// }
.edu-table .ant-table-tbody > tr > td {
height: 58px;
}
@ -4246,12 +4270,16 @@ class Listofworksstudentone extends Component {
}
`}</style>
<div className="edu-table edu-back-white ysltableowss table4">
{datas === undefined ? "" : <Table
dataSource={datas}
columns={columnsstu}
pagination={false}
loading={loadingstate}
/>}
{datas === undefined ? "" :
<Spin tip="正在加载..." spinning={loadingstate}>
<Table
dataSource={datas}
columns={columnsstu}
pagination={false}
loading={false}
/>
</Spin>
}
</div>
</div>
{
@ -4270,7 +4298,7 @@ class Listofworksstudentone extends Component {
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
<p className="edu-nodata-p mb30">{this.state.searchtypes===false?"暂时还没有相关数据哦!":"抱歉没有您要搜索的内容,请换个词语试试看"}</p>
</div>
</div>
</div>

@ -370,11 +370,11 @@ class ShixunWorkReport extends Component {
{this.props.isAdmin() ?<a
className=" color-blue font-14 fr ml20 mt15"
onClick={()=>this.confirmysl(`/student_works/${homeworkid}/export_shixun_work_report.pdf`)}
> <Spin size="small" spinning={this.state.isspinning}>导出实训报告数据</Spin></a>:
> <Spin size="small" spinning={this.state.isspinning}>导出实训报告</Spin></a>:
parseInt(this.props&&this.props.user.user_id)===parseInt(data&&data.user_id)?<a
className=" color-blue font-14 fr ml20 mt15"
onClick={()=>this.confirmysl(`/student_works/${homeworkid}/export_shixun_work_report.pdf`)}
> <Spin size="small" spinning={this.state.isspinning}>导出实训报告数据</Spin></a>:""
> <Spin size="small" spinning={this.state.isspinning}>导出实训报告</Spin></a>:""
}
{/*{this.props.isAdmin() ?work_comment_hidden===true? "":<a*/}
{/*className=" color-blue font-14 fr ml20 mt15"*/}
@ -465,22 +465,22 @@ class ShixunWorkReport extends Component {
</div>
<div className={"fl edu-back-white ml39 "}>
<p className={"back_font"}>{data&&data.username}</p>
<p className={"back_font mt10"}>{data&&data.username}</p>
<p className={"mb16"}>
<span className={"passbox"}>
<div className={"passfont"}><span className={"color999"}>通过关卡</span> <span className={"colorCF3B3B"}>{data&&data.complete_count}/{data&&data.challenges_count}</span></div>
<p className={"mb16 mt10"}>
<span className={"passbox "}>
<div className={"passfont mb5"}><span className={"color999"}>当前完成关卡</span> <span className={"colorCF3B3B"}>{data&&data.complete_count}/{data&&data.challenges_count}</span></div>
<div className={"passfontbom"}><span className={"color999"}>经验值</span> <span className={"color333"}>{data&&data.myself_experience}/{data&&data.total_experience}</span></div>
</span>
<span className={"passbox"}>
<div className={"passfontmid"}><span className={"color999"}>课堂最高完成效率</span> <span className={data&&data.max_efficiency===null?"color999":"color333"}>{data&&data.max_efficiency===null?'--':data&&data.max_efficiency}</span></div>
<div className={"passfontbommid"}><span className={"color999"}>完成效率</span> <span className={data&&data.efficiency===null?"color999":"color333"}>{data&&data.efficiency===null?'--':data&&data.efficiency}</span></div>
<div className={"passfontbommid mb5"}><span className={"color999"}>完成效率</span> <span className={data&&data.efficiency===null?"color999":"color333"}>{data&&data.efficiency===null?'--':data&&data.efficiency}</span></div>
<div className={"passfontmid "}><span className={"color999"}>课堂最高完成效率</span> <span className={data&&data.max_efficiency===null?"color999":"color333"}>{data&&data.max_efficiency===null?'--':data&&data.max_efficiency}</span></div>
</span>
<span className={"passbox"}>
<div><span className={"color999"}>通关时间</span> <span className={data&&data.passed_time===null?"color999":"color333"}>{data&&data.passed_time===null||data&&data.passed_time=== "--"?'--':moment(data&&data.passed_time).format('YYYY-MM-DD HH:mm')}</span></div>
<div><span className={"color999"}>实战耗时</span> <span className={data&&data.efficiency===null?"color999":"color333"}>{data&&data.time_consuming===null?'--':data&&data.time_consuming}</span></div>
{/*<div><span className={"color999"}>实战耗时:</span> <span className={data&&data.efficiency===null?"color999":"color333"}>{data&&data.time_consuming===null?'--':data&&data.time_consuming}</span></div>*/}
</span>
</p>

@ -2671,14 +2671,14 @@ class Trainingjobsetting extends Component {
className="ml15 font-14" style={{textAlign: "left", color: "#FF8204"}}>(总分值 = 效率分+ 关卡任务总分)</span>
</div>
<div className="yslflexhome">
<div style={{width: "700px"}}>
<div className="yslflexhomes mt9" style={{width: "802px", lineHeight: "35px", marginLeft: "114px"}}>
<div >
<div className="yslflexhomes mt9" style={{width: "1000px", lineHeight: "35px", marginLeft: "114px"}}>
<div className=" clearfix edu-back-white poll_list mt10">
<Checkbox disabled={!flagPageEdit} className=" font-16 mt10"
onChange={this.onChangeeffectiveness}
checked={this.state.work_efficiencys} style={{color: "#666666"}}>效率分<span
className={"font-14 color-grey-c font-16 ml15"}
style={{textAlign: "left"}}>(选中则学生最终成绩包含效率分)</span>
className={"font-13 color-grey-c ml15"}
style={{textAlign: "left"}}>(选中则学生最终成绩包含效率分效率分在作业截止或者补交结束后由系统自动生成)</span>
</Checkbox>
<div>
@ -2686,7 +2686,7 @@ class Trainingjobsetting extends Component {
</div>
<div>
<div className="yslflexhomes invite-tipysl">
<div className="yslflexhomes invite-tipysl" style={{width: "399px"}}>
<span className="to-back-left"></span>
<div className="padding20 invitecontent clearfix" style={{backgroundColor: " #FAFAFA"}}>
<p className="font-12 edu-txt-left">

@ -1,12 +1,10 @@
import React,{ Component } from "react";
import { Input,Checkbox,Table, Pagination, Modal,Menu, Tooltip,Spin } from "antd";
import { WordsBtn,on, off, trigger } from 'educoder';
import {BrowserRouter as Router,Route,Switch,Link} from 'react-router-dom';
import { Input,Checkbox, Pagination,Menu,Spin } from "antd";
import { WordsBtn,on, trigger ,publicSearchs} from 'educoder';
import {Link} from 'react-router-dom';
import axios from'axios';
import HomeworkModal from "../coursesPublic/HomeworkModal";
import OneSelfOrderModal from "../coursesPublic/OneSelfOrderModal";
import ShixunModal from "../coursesPublic/ShixunModal";
import PathModal from "../coursesPublic/PathModal";
import NewShixunModel from '../coursesPublic/NewShixunModel';
import AddcoursesNav from "../coursesPublic/AddcoursesNav";
import Modals from '../../modals/Modals';
@ -16,8 +14,6 @@ import '../css/busyWork.css'
import ShixunhomeWorkItem from "./ShixunhomeWorkItem";
import NoneData from "../coursesPublic/NoneData";
const Search = Input.Search;
class ShixunHomework extends Component{
constructor(props){
super(props);
@ -198,16 +194,20 @@ class ShixunHomework extends Component{
if(result.status===200){
this.setState({
datas:result.data,
isSpin:false
isSpin:false,
page:page
})
}
}else{
this.setState({
isSpin:false
isSpin:false,
})
}
}).catch((error)=>{
console.log(error);
this.setState({
isSpin:false
})
})
}
@ -644,19 +644,21 @@ class ShixunHomework extends Component{
}
SearchCoursenames=(e)=>{
this.setState({
Coursename:e.target.value
Coursename:e.target.value,
})
}
SearchCoursename=(value)=>{
let {page,order}=this.state;
this.setState({
Coursename:value
Coursename:value,
isSpin:true,
})
this.homeworkupdatalist(value,page,order);
this.homeworkupdatalist(value,1,order);
}
@ -1030,7 +1032,6 @@ class ShixunHomework extends Component{
}=this.state;
let main_id=this.props.match.params.main_id;
let category_id=this.props.match.params.category_id;
return(
<React.Fragment >
@ -1212,12 +1213,15 @@ class ShixunHomework extends Component{
</Menu>
</div>
<div className="fr mt16 mb16 searchView">
<Search
value={Coursename}
placeholder="请输入名称进行搜索"
onInput={this.SearchCoursenames}
onSearch={value => this.SearchCoursename(value)}
></Search>
{publicSearchs("请输入名称进行搜索",value => this.SearchCoursename(value),this.SearchCoursenames,(e)=>this.SearchCoursenames(e))}
{/*<Search*/}
{/* // value={Coursename}*/}
{/* placeholder="请输入名称进行搜索"*/}
{/* onInput={this.SearchCoursenames}*/}
{/* onSearch={value => this.SearchCoursename(value)}*/}
{/* onChange={(e)=>this.allowClearonChange(e)}*/}
{/* allowClear={true}*/}
{/*></Search>*/}
</div>
</div>
</div>
@ -1380,14 +1384,3 @@ class ShixunHomework extends Component{
}
}
export default ShixunHomework;
// {/*<div className="alltask "*/}
// {/*style={*/}
// {/*{*/}
// {/*display: datas===undefined?'none' :datas.task_count===0? 'block' : 'none'*/}
// {/*}*/}
// {/*}*/}
// {/*>*/}
// {/*<div className="edu-tab-con-box clearfix edu-txt-center">*/}
// {/*<img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />*/}
// {/*<p className="edu-nodata-p mb20">暂时还没有相关数据哦!</p></div>*/}
// {/*</div>*/}

@ -66,7 +66,7 @@ class ConclusionEvaluation extends Component {
</span>
),
},{
title: '最终成绩',
title: '当前成绩',
dataIndex: 'grade',
key: 'grade',
render: (text, record) => (
@ -81,7 +81,7 @@ class ConclusionEvaluation extends Component {
</span>
),
}, {
title: '实战耗时',
title: '实战耗时',
key: 'elapsed',
dataIndex: 'elapsed',

@ -0,0 +1,127 @@
/*
* @Description: 知识点
* @Author: tangjiang
* @Github:
* @Date: 2019-12-30 13:51:19
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-03 09:32:24
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
import { Select, notification } from 'antd';
const { Option } = Select;
function KnowLedge (props) {
const {
options = [], // 下拉选项
values = [], // 已选择的下拉项
onChange // 获取选择的值
} = props;
useEffect(() => {
const _options = [];
const _selects = [];
options.forEach(opt => {
if (!values.includes(opt.id)) {
_options.push(opt);
} else {
_selects.push(opt);
}
});
setSelectOptions(_options || []);
setSelectValue(_selects || []);
}, [props]);
// 显示的下拉项
const [selectOptions, setSelectOptions] = useState(options);
// 已选择的下拉项
const [selectValue, setSelectValue] = useState([]);
//
const [value] = useState([]);
// 渲染下拉选项
const renderOptions = (options = []) => {
return options.map((opt, i) => (
<Option key={`opt_${i}`} value={`${opt.id}`}>{opt.name}</Option>
));
}
// 过滤下拉列表项
const handleSelectChange = (value) => {
value = +value.join('');
const tempArr = [...selectValue];
const _result = selectOptions.filter(item => {
if (item.id === value && tempArr.findIndex(t => t.id === value) === -1) {
tempArr.push(item);
}
return item.id !== value;
});
if (tempArr.length > 50) {
notification.warning({
message: '提示',
description: '知识点不能超过50个'
});
return;
}
setSelectValue(tempArr);
setSelectOptions(_result);
// 将选择值返回
onChange && onChange(tempArr);
}
// 删除
const handleRemoveResult = (item) => {
// console.log('点击了删除按钮===>>>>', item);
// 将删除的值重新加入到列表中
const tempOptions = [...selectOptions];
const tempValue = selectValue.filter(t => t.id !== item.id);
// console.log(selectValue);
tempOptions.push(item);
setSelectOptions(tempOptions);
setSelectValue(tempValue);
// 将选择值返回
onChange && onChange(tempValue);
}
// 渲染下拉结果
const renderResult = (arrs) => {
return arrs.map((item) => (
<span className="knowledge-item" key={`item_${item.name}`}>
{item.name}
<span
onClick={() => handleRemoveResult(item)}
className="iconfont icon-roundclose knowledge-close"
></span>
</span>
));
}
// 渲染下拉列表
const renderSelect = (options = []) => {
// console.log('+++++', options);
// setSelectValue(_selects);
return (
<Select
value={value}
mode="tags"
placeholder="请选择"
style={{ width: '100%' }}
onChange={handleSelectChange}
>
{renderOptions(options)}
</Select>
)
}
return (
<div className="knowledge-select-area">
{ renderSelect(selectOptions) }
{/* 渲染下拉选择项 */}
<div className="knowledge-result">
{ renderResult(selectValue) }
</div>
</div>
);
}
export default KnowLedge;

@ -0,0 +1,42 @@
.knowledge-select-area{
.ant-select-selection__rendered{
margin-bottom: 0 !important;
}
.ant-select-search--inline{
margin-left: 5px;
margin-top: 2px;
}
.knowledge-result{
display: flex;
flex-direction: row;
flex-wrap: wrap;
// margin-top: 15px;
.knowledge-item{
position: relative;
border: 1px solid #DDDDDD;
border-radius: 3px;
padding: 10px;
background: #fff;
margin-right: 10px;
margin-top: 10px;
// margin-bottom: 10px;
.knowledge-close{
display: none;
position: absolute;
right: -10px;
top: -10px;
background-color: rgba(250,250,250,1);
cursor: pointer;
}
&:hover{
.knowledge-close{
display: block;
}
}
}
}
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 15:02:52
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 20:49:46
* @LastEditTime : 2020-01-02 13:59:38
*/
import './index.scss';
import React, { useState, useRef, useEffect } from 'react';

@ -35,6 +35,7 @@ const NewOrEditTask = (props) => {
getUserInfoForNew,
handleCancelPublish,
validateOjForm,
getQuestion
// updateTestAndValidate,
} = props;
@ -53,6 +54,10 @@ const NewOrEditTask = (props) => {
useEffect(() => {
// 获取用户信息
getUserInfoForNew();
// 获取课程列表
getQuestion({
source: 'question'
});
// console.log('获取路由参数: ====', props.match.params);
const id = props.match.params.id;
// 保存OJForm的id号指明是编辑还是新增
@ -273,7 +278,8 @@ const mapDispatchToProps = (dispatch) => ({
startProgramQuestion: (id, props) => dispatch(actions.startProgramQuestion(id, props)),
// 新建时获取信息
getUserInfoForNew: () => dispatch(actions.getUserInfoForNew()),
validateOjForm: (props, type, cb) => dispatch(actions.validateOjForm(props, type, cb))
validateOjForm: (props, type, cb) => dispatch(actions.validateOjForm(props, type, cb)),
getQuestion: (params) => dispatch(actions.getQuestion(params))
});
export default withRouter(connect(

@ -4,12 +4,12 @@
* @Github:
* @Date: 2019-11-20 10:35:40
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 14:30:55
* @LastEditTime : 2020-01-03 11:28:26
*/
import './index.scss';
// import 'katex/dist/katex.css';
import React from 'react';
import { Form, Input, Select, InputNumber, Button } from 'antd';
import { Form, Input, Select, InputNumber, Button, Cascader, notification } from 'antd';
import { connect } from 'react-redux';
import AddTestDemo from './AddTestDemo';
// import QuillEditor from '../../../quillEditor';
@ -18,6 +18,7 @@ import CONST from '../../../../../constants';
import { toStore } from 'educoder'; // 保存和读取store值
// import Wrapper from '../../../../../common/reactQuill';
import QuillForEditor from '../../../../../common/quillForEditor';
import KnowLedge from '../../../components/knowledge';
const scrollIntoView = require('scroll-into-view');
const {jcLabel} = CONST;
const FormItem = Form.Item;
@ -59,7 +60,9 @@ class EditTab extends React.Component {
scrollHeight: 0, // 滚动元素的高度
top: 500,
bottom: 20,
offsetTop: 0
offsetTop: 0,
// knowledges: [],
// coursers: [] // 选中的课程
}
}
@ -77,9 +80,17 @@ class EditTab extends React.Component {
}, () => {
this.state.scrollEl.addEventListener('scroll', this.handleScroll, false);
});
// 获取题库
// this.props.getQuestion({
// source: 'question'
// });
}
componentWillUnmount () {
// componentDidUpdate (nextProp) {
// console.log(nextProp);
// }
componentWillUnmount (nextPro) {
this.state.scrollEl.removeEventListener('scroll', this.handleScroll, false);
}
@ -125,9 +136,26 @@ class EditTab extends React.Component {
handleTimeLimitChange = (value) => {
this.props.validateOjTimeLimit(value);
}
// 改变分类
handleChangeCategory = (value) => {
this.props.validateOjCategory(value);
// 改变方向
handleChangeSubDisciplineId = (value) => {
// 课程下拉值变化时, 同步更新知识点
const { courseQuestions, saveKnowledge } = this.props;
saveKnowledge([]);
// 获取当前分类下的知识点
courseQuestions.forEach(item => {
if (value[0] && item.id === value[0]) {
item.sub_disciplines && item.sub_disciplines.forEach(c => {
if (value[1] && c.id === value[1]) {
saveKnowledge(c.tag_disciplines)
console.log(c.tag_disciplines);
} else if (!value[1]) {
saveKnowledge([]);
}
});
}
});
// this.props.validateOjCategory(value[1] || '');
this.props.validateOjSubDisciplineId(value[1] || '');
}
// 改变公开程序
handleChangeOpenOrNot = (value) => {
@ -146,13 +174,18 @@ class EditTab extends React.Component {
addTestCase, // 添加测试用例
deleteTestCase, // 删除测试用例
testCasesValidate,
openTestCodeIndex = []
openTestCodeIndex = [],
courseQuestions,
tag_discipline_id,
knowledges
} = this.props;
console.log('knowledge======>>>>>>', knowledges);
// const {knowledges} = this.state;
// 表单label
const myLabel = (name, subTitle) => {
const myLabel = (name, subTitle, nostar) => {
if (subTitle) {
return (
<span className={'label_text'}>
<span className={`label_text ${nostar}`}>
{name}
<span className={'label_sub_text'}>
({subTitle})
@ -161,7 +194,7 @@ class EditTab extends React.Component {
)
} else {
return (
<span className={'label_text'}>{name}</span>
<span className={`label_text ${nostar}`}>{name}</span>
)
}
};
@ -197,7 +230,14 @@ class EditTab extends React.Component {
};
// 添加测试用例
const handleAddTest = () => {
const {position} = this.props;
const {position, testCases = []} = this.props;
if (testCases.length >= 50) {
notification.warning({
message: '提示',
description: '测试用例不能超过50个'
});
return;
}
const obj = { // 测试用例参数
input: '',
output: '',
@ -235,15 +275,75 @@ class EditTab extends React.Component {
}
// 编辑器配置信息
const quillConfig = [
[{ header: [1, 2, 3, 4, 5, 6, false] }],
['bold', 'italic', 'underline', 'strike'], // 切换按钮
['blockquote', 'code-block'], // 代码块
[{align: []}, { 'list': 'ordered' }, { 'list': 'bullet' }], // 列表
[{ 'script': 'sub'}, { 'script': 'super' }],
[{ 'color': [] }, { 'background': [] }], // 字体颜色与背景色
['image', 'formula'], // 数学公式、图片、视频
['clean'], // 清除格式
{ header: 1}, {header: 2},
// {size: ['12px', '14px', '16px', '18px', '20px', false]},
'bold', 'italic', 'underline', 'strike', // 切换按钮
'blockquote', 'code-block', // 代码块
{align: []}, { 'list': 'ordered' }, { 'list': 'bullet' }, // 列表
{ 'script': 'sub'}, { 'script': 'super' },
{ 'color': [] }, { 'background': [] }, // 字体颜色与背景色
// {font: []},
'image', 'formula', // 数学公式、图片、视频
'clean', // 清除格式
];
const renderCourseQuestion = (arrs) => {
const tempArr = [];
const sub_id = this.props.ojForm.sub_discipline_id;
function loop (arrs, tempArr) {
arrs.forEach(item => {
const obj = {};
obj.value = item.id;
obj.label = item.name;
// 当item下还有子元素时递归调用
if (item.sub_disciplines) {
arrs = item.sub_disciplines;
obj.children = [];
loop(arrs, obj.children);
}
tempArr.push(obj);
});
}
loop(arrs, tempArr);
// 获取选中的下拉值
let choid_ids = [];
// let tempKnowledges = [];
tempArr.forEach(t => {
// debugger;
if (sub_id && t.children) {
t.children.forEach(c => {
if (c.value === sub_id) {
choid_ids = [t.value, c.value];
// tempKnowledges = c.children || [];
}
});
}
});
console.log(choid_ids);
return (
<Cascader
placeholder="请选择"
options={tempArr}
expandTrigger="hover"
value={choid_ids}
// onChange={this.handleChangeCategory}
onChange={this.handleChangeSubDisciplineId}
/>
)
}
// 知识点
const handleKnowledgeChange = (values= []) => {
const _result = [];
values.forEach(v => {
_result.push(v.id);
});
console.log('下拉选择的值:===>>>', _result);
// 保存选择的知识点
this.props.saveTagDisciplineId(_result);
}
return (
<div className={'editor_area'} id="textCase">
@ -262,16 +362,34 @@ class EditTab extends React.Component {
<FormItem
className={`input_area flex_50 flex_50_right`}
label={<span>{myLabel(jcLabel['category'], '合理的分类有利于快速检索')}</span>}
validateStatus={ojFormValidate.category.validateStatus}
help={ojFormValidate.category.errMsg}
label={<span>{myLabel(jcLabel['sub_discipline_id'], '合理的课程分类有利于快速检索')}</span>}
validateStatus={ojFormValidate.sub_discipline_id.validateStatus}
help={ojFormValidate.sub_discipline_id.errMsg}
colon={ false }
>
<Select onChange={this.handleChangeCategory} value={`${ojForm.category}`}>
{/* <Select onChange={this.handleChangeCategory} value={`${ojForm.category}`}>
{getOptions('category')}
</Select>
</Select> */}
{/* <Cascader
options={courseQuestions}
expandTrigger="hover"
onChange={this.handleChangeCategory}
/> */}
{ renderCourseQuestion(courseQuestions)}
</FormItem>
<FormItem
colon={ false }
className='input_area flex_100'
label={<span>{myLabel(jcLabel['knowledge'], '', 'nostar')}</span>}
>
<KnowLedge
options={knowledges}
values={tag_discipline_id}
onChange={handleKnowledgeChange}
/>
</FormItem>
<FormItem
className={`input_area flex_50 flex_50_left`}
label={<span>{myLabel(jcLabel['timeLimit'], '程序允许时间限制时长,单位:秒')}</span>}
@ -317,16 +435,13 @@ class EditTab extends React.Component {
help={ojFormValidate.description.errMsg}
colon={ false }
>
<div style={{ marginTop: '15px'}}>
<QuillForEditor
<QuillForEditor
style={{ height: '200px' }}
placeholder="请输入描述信息"
onContentChange={handleContentChange}
options={quillConfig}
value={ojForm.description}
/>
</div>
</FormItem>
{/* <FormItem
@ -366,14 +481,21 @@ const mapStateToProps = (state) => {
testCases,
openTestCodeIndex,
testCasesValidate,
ojFormValidate} = ojFormReducer;
ojFormValidate,
courseQuestions,
tag_discipline_id,
knowledges
} = ojFormReducer;
return {
ojForm,
testCases,
testCasesValidate,
ojFormValidate,
position,
openTestCodeIndex
openTestCodeIndex,
courseQuestions,
tag_discipline_id,
knowledges
};
};
@ -386,10 +508,15 @@ const mapDispatchToProps = (dispatch) => ({
validateOjTimeLimit: (value) => dispatch(actions.validateOjTimeLimit(value)),
validateOjCategory: (value) => dispatch(actions.validateOjCategory(value)),
validateOpenOrNot: (value) => dispatch(actions.validateOpenOrNot(value)),
validateOjSubDisciplineId: (value) => dispatch(actions.validateOjSubDisciplineId(value)),
saveTagDisciplineId: (value) => dispatch(actions.saveTagDisciplineId(value)),
// 新增测试用例
addTestCase: (value) => dispatch(actions.addTestCase(value)),
// 删除测试用例
deleteTestCase: (value) => dispatch(actions.deleteTestCase(value)),
saveKnowledge: (value) => dispatch(actions.saveKnowledge(value))
// 获取题库
// getQuestion: (params) => dispatch(actions.getQuestion(params))
});
export default connect(

@ -18,6 +18,12 @@
line-height: 1;
content: '*';
}
&.nostar{
&::before {
content: ''
}
}
}
.input_area{
display: inline-block;

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-12-04 08:36:21
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 21:18:39
* @LastEditTime : 2020-01-02 13:48:02
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
@ -57,7 +57,9 @@ function RecordDetail (props) {
const handleReturn = (identifier) => {
if (identifier) {
saveEditorCodeForDetail('');
props.history.push(`/myproblems/${identifier}`);
setTimeout(() => {
props.history.push(`/myproblems/${identifier}`);
}, 300);
}
}

@ -23,6 +23,8 @@
}
.header_title{
font-size: 16px;
font-weight: bold;
text-align: center;
}
@ -82,6 +84,8 @@
bottom: 0;
top: 0;
text-align: center;
font-size: 16px;
font-weight: bold;
}
}
}
@ -158,6 +162,22 @@
-moz-background-clip: padding;
-webkit-background-clip: padding;
background-clip: padding-box;
// &::before{
// position: absolute;
// width: 24px;
// height: 24px;
// border-radius: 50%;
// margin-top: -12px;
// top: 50%;
// right: -12px;
// font-family: 'iconfont';
// background: gold;
// content: '\e711';
// font-size: 18px;
// text-align: center;
// line-height: 24px;
// }
}
.Resizer:hover {
@ -196,4 +216,4 @@
}
.Resizer.disabled:hover {
border-color: transparent;
}
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-23 11:33:41
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 16:03:04
* @LastEditTime : 2020-01-02 13:51:22
// */
import './index.scss';
import React, { useState, useEffect, useMemo } from 'react';
@ -50,8 +50,6 @@ const LeftPane = (props) => {
record: (<CommitRecord />),
comment: (<Comment />)
};
console.log('======>>>>>>>', props);
useEffect(() => {
setDefaultActiveKey(userCodeTab);

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 14:59:51
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 19:23:46
* @LastEditTime : 2020-01-02 14:23:43
*/
import React, { useState, useEffect } from 'react';
import {connect} from 'react-redux';
@ -39,7 +39,7 @@ const RightPane = (props) => {
changeLoadingState
} = props;
const [editorCode, setEditorCode] = useState(editor_code || hack.code);
// const [editorCode, setEditorCode] = useState(editor_code || hack.code);
const [noteClazz, setNoteClazz] = useState('editor_nodte_area');
const [noteCount] = useState(5000);
// const [code, setCode] = useState(editor_code || hack.code);
@ -65,8 +65,9 @@ const RightPane = (props) => {
let timer = null; // 定时器
// 代码块内容变化时
const handleCodeChange = (value) => {
// console.log('编辑器代码 ======》》》》》》》》》++++++++++', value);
saveUserInputCode(value);
setEditorCode(value);
// setEditorCode(value);
if (!timer) {
timer = setInterval(function () {
clearInterval(timer);
@ -116,6 +117,7 @@ const RightPane = (props) => {
const { getFieldDecorator } = props.form;
return (
<div className={'right_pane_code_wrap'}>
<MyMonacoEditor
notice={notice}
identifier={identifier}

@ -87,15 +87,16 @@
right: 150px;
top: 0;
height: 34px;
background: gold;
line-height: 32px;
/* background: gold; */
}
.code_evalute_icon{
position: absolute;
top: 0;
width: 56px;
height: 28px;
width: 54px;
height: 27px;
left: 50%;
margin-left: -28px;
margin-left: -27px;
background: rgba(42,58,79,1);
z-index: 10;
border-bottom-left-radius: 100px;
@ -106,6 +107,15 @@
opacity: .4;
transition: all .3s;
}
.code_evalute_icon:hover{
opacity: 1;
}
.btn-arrow{
position: relative;
bottom: 3px;
font-size: 14px !important;
}
@keyframes mymove
{

@ -2,7 +2,7 @@ import React, { Component } from 'react';
import axios from 'axios'
import { Spin, Icon } from 'antd'
import ClipboardJS from 'clipboard'
import { connect } from 'react-redux';
import VNCDisplay from './VNCDisplay'
import FloatButton from './component/FloatButton'
import SecondDrawer from './component/SecondDrawer'
@ -202,13 +202,17 @@ class VNCContainer extends Component {
onSelect={onTreeSelect}
*/
render() {
const { challenge, vnc_url, git_url } = this.props
const { challenge, vnc_url, git_url, showOrHide, isCollapse } = this.props
const _classCtx = this.state.bottomDrawer ? 'btn_test_case_active' : 'btn_test_case';
const _classes = this.state.bottomDrawer
? `iconfont icon-xiajiantou btn-arrow`
: 'iconfont icon-shangjiantou btn-arrow';
const secondDrawerChildren = this.renderSecondDrawerChildren();
const _drawClasses = showOrHide
? ('codeEvaluateDrawer code_evaluate_stretch')
: (isCollapse ? 'codeEvaluateDrawer active' : 'codeEvaluateDrawer');
return (
<React.Fragment>
<SecondDrawer
@ -225,9 +229,20 @@ class VNCContainer extends Component {
<style>{`
/* 评测结果 */
.codeEvaluateDrawer{
// position: absolute;
// bottom: 84px;
position: absolute;
bottom: 84px;
transition: all .3s;
// bottom: px;
}
.codeEvaluateDrawer.active{
bottom: 50px;
}
.code_evaluate_stretch{
top: 0px;
}
.codeEvaluateDrawer #game_test_set_results {
height: 198px;
}
@ -242,6 +257,14 @@ class VNCContainer extends Component {
background: rgb(5, 16, 26) !important;
}
.code_evaluate_stretch .ant-drawer-content-wrapper{
height: 100% !important;
}
.code_evaluate_stretch #game_test_set_results {
height: calc(100vh - 136px) !important;
}
.codeEvaluateFloatButton {
bottom: 180px !important;
left: unset;
@ -348,12 +371,12 @@ class VNCContainer extends Component {
width={firstDrawerWidth}
closable={false}
onClose={this.onBottomDrawerClose}
visible={this.state.bottomDrawer===undefined?false:this.state.bottomDrawer}
className={'codeEvaluateDrawer'}
visible={isCollapse}
className={_drawClasses}
placement="bottom"
getContainer={false}
// style={{ position: 'absolute', bottom: '-25px', zIndex: 1 }}
style={{ position: 'absolute', bottom: '50px', zIndex: 1 }}
// style={{ position: 'absolute', bottom: '50px', top: 0, zIndex: 1 }}
afterVisibleChange={(visible) => {
if (visible) {
const canvas = $('.vncDisply canvas')[0]
@ -364,9 +387,9 @@ class VNCContainer extends Component {
>
{ this.props.codeEvaluate }
</Drawer>
<FloatButton onClick={this.swtichBottomDrawer}
{/* <FloatButton onClick={this.swtichBottomDrawer}
className="codeEvaluateFloatButton"
>测试集</FloatButton>
>测试集</FloatButton> */}
{/* <div
className={_classCtx}
onClick={this.swtichBottomDrawer}
@ -382,4 +405,14 @@ class VNCContainer extends Component {
}
}
export default VNCContainer;
const mapStateToProps = (state) => {
const { showOrHide, isCollapse } = state.tpiReducer;
return {
showOrHide,
isCollapse
}
};
export default connect(
mapStateToProps
)(VNCContainer);

@ -4,10 +4,11 @@ import React, { Component } from 'react';
import IconButton from 'material-ui/IconButton';
import Tooltip from 'material-ui/Tooltip';
import Button from 'material-ui/Button';
import { connect } from 'react-redux';
import './CodeEvaluateView.css'
import { CircularProgress } from 'material-ui/Progress';
import { on, off } from 'educoder'
import actions from '../../../redux/actions';
const testSetsExpandedArrayInitVal = [false, false, false, false, false,
false, false, false, false, false,
false, false, false, false, false,
@ -274,9 +275,24 @@ class CodeEvaluateView extends Component {
})
}
onHandleTestCase () {
// console.log(this);
const {showOrHide, showOrHideTpiTestCase} = this.props;
showOrHideTpiTestCase(!showOrHide);
}
handleShowTestCase () {
// console.log('111111111');
const {isCollapse, isCollpaseTsetCase, showOrHideTpiTestCase} = this.props;
isCollpaseTsetCase(!isCollapse);
if (isCollapse) {
showOrHideTpiTestCase(false);
}
}
render() {
const { evaluateViewExpanded, tabIndex } = this.state;
const { output_sets, latest_output, record, challenge, gameBuilding, myshixun } = this.props;
const { output_sets, latest_output, record, challenge, gameBuilding, myshixun, showOrHide, isCollapse } = this.props;
if (!output_sets) {
return (
@ -300,6 +316,8 @@ class CodeEvaluateView extends Component {
onclick="check_tab('blacktab_con','blacktab_hover',this);"
*/
const _arrowClasses = isCollapse ? 'iconfont icon-xiajiantou btn-arrow' : 'iconfont icon-shangjiantou btn-arrow';
return (
<React.Fragment>
<ul id="blacktab_nav">
@ -312,17 +330,20 @@ class CodeEvaluateView extends Component {
<li className={`blacktab_con ${ tabIndex === 1 ? 'tab_hover' : ''}`} onClick={() => this.tabIndexChange(1)}>
<a href="javascript:void(0);" className="tab_type tab_color">测试结果</a>
</li>
{/* <li className="blacktab_con_abs">
<span className="code_evalute_icon">
<span className="iconfont icon-xiajiantou btn-arrow"></span>
<li className="blacktab_con_abs">
<span className="code_evalute_icon" onClick={() => this.handleShowTestCase()}>
<span className={_arrowClasses}></span>
</span>
</li> */}
</li>
{this.props.inDrawer ? <Tooltip id="tooltip-icon-expand" title={ "收起" }>
{this.props.inDrawer ? <Tooltip id="tooltip-icon-expand" title={ showOrHide ? "收起" : "展开"}>
{/*TODO 按钮大小改造css*/}
{/* icon-guanbi */}
<a className="iconButton fr mr15 mt4" onClick={this.props.hideCodeEvaluate} id="extend_and_zoom" >
{/* <a className="iconButton fr mr15 mt4" onClick={this.props.hideCodeEvaluate} id="extend_and_zoom" >
<i className={ "font-18 iconfont icon-guanbi" }></i>
</a> */}
<a style={{ display: isCollapse ? 'inline-block' : 'none'}} className="iconButton fr mr15" id="extend_and_zoom" onClick={() => this.onHandleTestCase()}>
<i className={ showOrHide ? "font-18 iconfont icon-shousuo" : "iconfont icon-zhankai font-18" }></i>
</a>
</Tooltip> : <Tooltip id="tooltip-icon-expand" title={ evaluateViewExpanded ? "" : ""}>
@ -398,4 +419,19 @@ class CodeEvaluateView extends Component {
}
}
export default CodeEvaluateView;
const mapStateToProps = (state) => {
const { showOrHide, isCollapse } = state.tpiReducer;
return {
showOrHide,
isCollapse
}
};
const mapDispatchToProps = (dispatch) => ({
showOrHideTpiTestCase: (flag) => dispatch(actions.showOrHideTpiTestCase(flag)),
isCollpaseTsetCase: (flag) => dispatch(actions.isCollpaseTsetCase(flag))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(CodeEvaluateView);

@ -160,7 +160,7 @@
.newyslusercjz{
display: inline-block;
position: absolute;
bottom: 0px;
bottom: 10px;
left: -18px;
width: 44px;
height: 18px;

@ -18,7 +18,9 @@ const types = {
VALIDATE_OJ_DIFFICULT: 'VALIDATE_OJ_DIFFICULT', // 难易度
VALIDATE_OJ_TIMELIMIT: 'VALIDATE_OJ_TIMELIMIT', // 时间限制
VALIDATE_OJ_CATEGORY: 'VALIDATE_OJ_CATEGORY', // 分类
VALIDATE_OJ_SUB_DISCIPLINE_ID: 'VALIDATE_OJ_SUB_DISCIPLINE_ID', // 方向
VALIDATE_OJ_OPENORNOT: 'VALIDATE_OJ_OPENORNOT', // 公开程序
SAVE_TAG_DISCIPLINE_ID: 'SAVE_TAG_DISCIPLINE_ID', // 保存知识点
SAVE_OJ_FORM: 'SAVE_OJ_FORM', // 保存表单
ADD_TEST_CASE: 'ADD_TEST_CASE', // 添加测试用例
DELETE_TEST_CASE: 'DELETE_TEST_CASE', // 删除测试用例
@ -32,6 +34,10 @@ const types = {
TEST_CASE_INPUT_CHANGE: 'TEST_CASE_INPUT_CHANGE', // 测试用例输入值改变时
TEST_CASE_OUTPUT_CHANGE: 'TEST_CASE_OUTPUT_CHANGE', // 测试用例输出值改变时
DEBUGGER_CODE: 'DEBUGGER_CODE', // 调试代码
GET_COURSE_QUESTION: 'GET_COURSE_QUESTION', // 获取编辑题
CHANGE_KNOWLEDGES: 'CHANGE_KNOWLEDGES', // 保存所选择的知识点
SET_OJ_INITIAL_VALUE: 'SET_OJ_INITIAL_VALUE', // 设置初始值
// study
SAVE_USER_PROGRAM_ID: 'SAVE_USER_PROGRAM_ID',// 保存用户编程题id值
USER_PROGRAM_DETAIL: 'USER_PROGRAM_DETAIL', // 用户编程题详情
SHOW_OR_HIDE_CONTROL: 'SHOW_OR_HIDE_CONTROL', // 显示或隐藏控制台
@ -79,6 +85,9 @@ const types = {
DELETE_COMMENTS: 'DELETE_COMMENTS', // 删除评论
SAVE_COMMENT_IDENTIFIER: 'SAVE_COMMENT_IDENTIFIER', // 评论时的identifier
CHANGE_COMMENT_PAGINATION_PARAMS: 'CHANGE_COMMENT_PAGINATION_PARAMS', // 改变分页
/** tpi */
SHOW_OR_HIDE_TPI_TEST_CASE: 'SHOW_OR_HIDE_TPI_TEST_CASE', // 显示或隐藏tpi测试集弹框
IS_COLLAPSE_TEST_CASE: 'IS_COLLAPSE_TEST_CASE' // 是否展开测试集
}
export default types;

@ -25,6 +25,8 @@ import {
validateOjTimeLimit,
validateOjCategory,
validateOpenOrNot,
validateOjSubDisciplineId,
saveTagDisciplineId,
addTestCase,
deleteTestCase,
testCaseInputChange,
@ -32,6 +34,9 @@ import {
updateTestAndValidate,
updateOpenTestCaseIndex,
handleClickCancelPublish,
getQuestion,
saveKnowledge,
setOjInitialValue
} from './ojForm';
import {
@ -92,6 +97,11 @@ import {
updataspinning
} from './jupyter';
import {
showOrHideTpiTestCase,
isCollpaseTsetCase
} from './tpi';
export default {
toggleTodo,
getOJList,
@ -109,7 +119,13 @@ export default {
validateOjTimeLimit,
validateOjCategory,
validateOpenOrNot,
validateOjSubDisciplineId,
saveTagDisciplineId,
handleClickCancelPublish,
getQuestion,
saveKnowledge,
setOjInitialValue,
//
addTestCase,
deleteTestCase,
testCaseInputChange,
@ -160,5 +176,8 @@ export default {
deleteComment,
likeComment,
showOrHideComment,
changePagination
changePagination,
// tpi
showOrHideTpiTestCase,
isCollpaseTsetCase
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 13:42:11
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 11:06:09
* @LastEditTime : 2020-01-02 14:17:49
*/
import types from "./actionTypes";
import { Base64 } from 'js-base64';
@ -116,16 +116,15 @@ export const saveUserCodeForInterval = (identifier, code) => {
});
// console.log('+++', userCode);
fetchUpdateCode(identifier, {
code: userCode
code: Base64.encode(userCode)
}).then(res => {
if (res.data.status === 401) {
return;
};
dispatch({
type: types.RESTORE_INITIAL_CODE,
payload: userCode
});
// dispatch({
// type: types.RESTORE_INITIAL_CODE,
// payload: userCode
// });
setTimeout(() => {
dispatch({
type: types.AUTO_UPDATE_CODE,
@ -342,7 +341,7 @@ export const getUserCommitRecord = (identifier) => {
export const getUserCommitRecordDetail = (identifier) => {
return (dispatch) => {
fetchUserCommitRecordDetail(identifier).then(res => {
console.log('提交记录详情======》》》》', res);
// console.log('提交记录详情======》》》》', res);
const { data } = res;
if (data.status === 401) return;
dispatch({

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 16:35:46
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 22:19:15
* @LastEditTime : 2020-01-03 16:40:54
*/
import types from './actionTypes';
import CONST from '../../constants';
@ -12,7 +12,8 @@ import {
fetchPostOjForm,
fetchGetOjById,
publishTask,
cancelPublicTask
cancelPublicTask,
fetchQuestion
} from '../../services/ojService';
import { Base64 } from 'js-base64';
import { notification } from 'antd';
@ -45,6 +46,10 @@ const maps = {
label: jcLabel['category'],
type: types.VALIDATE_OJ_CATEGORY
},
sub_discipline_id: {
label: jcLabel['sub_discipline_id'],
type: types.VALIDATE_OJ_SUB_DISCIPLINE_ID
},
openOrNot: {
label: jcLabel['openOrNot'],
type: types.VALIDATE_OJ_OPENORNOT
@ -105,21 +110,24 @@ export const validateOjForm = (props, type, cb) => {
const {ojForm, testCases, identifier, code } = getState().ojFormReducer;
// console.log('code', code);
/** 表单验证开始 */
let keys = Object.keys(ojForm);
// let keys = Object.keys(ojForm).filter(k => k !== '');
let keys = Object.keys(ojForm)
// 循环判断每个字段是否为空
let hasSuccess = true;
keys.forEach(key => {
const value = ojForm[key];
const validateResult = emptyValidate(key, value);
const errMsg = validateResult[key].errMsg;
if (errMsg) {
hasSuccess = false;
dispatch(
{
type: maps[key].type,
payload: payloadInfo(key, value, errMsg, validateResult[key])
}
)
if (!['category'].includes(key)) {
const value = ojForm[key];
const validateResult = emptyValidate(key, value);
const errMsg = validateResult[key].errMsg;
if (errMsg) {
hasSuccess = false;
dispatch(
{
type: maps[key].type,
payload: payloadInfo(key, value, errMsg, validateResult[key])
}
)
}
}
});
// 验证测试用例中的数组是否都有对应的值
@ -197,8 +205,8 @@ export const validateOjForm = (props, type, cb) => {
if (hasSuccess) {
// console.log('表单保存的数据为: ', getState());
const {ojFormReducer} = getState();
const {code, score, ojForm, testCases = []} = ojFormReducer;
const {category, description, difficult, language, name, openOrNot, timeLimit} = ojForm;
const {code, score, ojForm, testCases = [], tag_discipline_id = []} = ojFormReducer;
const {category, description, difficult, language, name, openOrNot, timeLimit, sub_discipline_id} = ojForm;
let paramsObj = {};
const hack = { // 编程题干
name,
@ -207,6 +215,8 @@ export const validateOjForm = (props, type, cb) => {
category,
'open_or_not': openOrNot,
'time_limit': timeLimit,
sub_discipline_id,
// tag_discipline_id,
score
};
@ -223,7 +233,8 @@ export const validateOjForm = (props, type, cb) => {
paramsObj['params'] = {
hack,
hack_sets: tempTc,
hack_codes
hack_codes,
tags: tag_discipline_id
}
paramsObj['submitType'] = 'add';
} else { // 存在时调用更新接口
@ -242,7 +253,8 @@ export const validateOjForm = (props, type, cb) => {
hack,
hack_sets,
hack_codes,
update_hack_sets
update_hack_sets,
tags: tag_discipline_id
}
paramsObj['submitType'] = 'update';
paramsObj['identifier'] = identifier;
@ -483,6 +495,15 @@ export const validateOjCategory = (value) => {
payload: payloadInfo('category', value, errMsg, validate)
}
};
// 验证方向
export const validateOjSubDisciplineId = (value) => {
const validate = emptyValidate('sub_discipline_id', value)['sub_discipline_id'];
const errMsg = validate.errMsg;
return {
type: types.VALIDATE_OJ_SUB_DISCIPLINE_ID,
payload: payloadInfo('sub_discipline_id', value, errMsg, validate)
}
};
// 验证公开程序
export const validateOpenOrNot = (value) => {
const validate = emptyValidate('openOrNot', value)['openOrNot'];
@ -492,6 +513,14 @@ export const validateOpenOrNot = (value) => {
payload: payloadInfo('openOrNot', value, errMsg, validate)
}
};
// 保存知识点
export const saveTagDisciplineId = (value) => {
// console.log('====????????????', value);
return {
type: types.SAVE_TAG_DISCIPLINE_ID,
payload: value
};
}
// 新增测试用例
export const addTestCase = (obj) => {
return {
@ -622,7 +651,6 @@ export const testCaseOutputChange = (value, index) => {
// // 调试代码时,更改对应的状态值
// export const changeTestCodeStatus = () => {
// 更新测试用命及验证
export const updateTestAndValidate = (obj) => {
return (dispatch) => {
@ -644,3 +672,41 @@ export const updateOpenTestCaseIndex = (value) => {
payload: value
}
}
// 获取课程题库
export const getQuestion = (params) => {
return (dispatch) => {
fetchQuestion(params).then(res => {
const { data = {} } = res;
const { disciplines = [] } = data;
dispatch({
type: types.GET_COURSE_QUESTION,
payload: disciplines
})
})
}
}
// 保存所选择的知识点
export const saveKnowledge = (values) => {
return {
type: types.CHANGE_KNOWLEDGES,
payload: values
}
}
/**
* 新增时跳转到OJ时带的默认参数:
* @param {}} params
* {
* difficult: '', // 难易度
* sub_discipline_id: '' // 课程方向
* tag_discipline_id [] 知识点
* }
*/
export const setOjInitialValue = (params) => {
return {
type: types.SET_OJ_INITIAL_VALUE,
payload: params
}
}

@ -0,0 +1,23 @@
/*
* @Description:
* @Author: tangjiang
* @Github:
* @Date: 2020-01-03 10:24:43
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-03 11:45:22
*/
import types from './actionTypes';
export const showOrHideTpiTestCase = (flag) => {
return {
type: types.SHOW_OR_HIDE_TPI_TEST_CASE,
payload: flag
}
}
export const isCollpaseTsetCase = (flag) => {
return {
type: types.IS_COLLAPSE_TEST_CASE,
payload: flag
}
}

@ -15,6 +15,7 @@ import commonReducer from './commonReducer';
import userReducer from './userReducer';
import jupyterReducer from './jupyterReducer';
import commentReducer from './commentReducer';
import tpiReducer from './tpiReducer';
export default combineReducers({
testReducer,
@ -24,5 +25,6 @@ export default combineReducers({
commonReducer,
userReducer,
jupyterReducer,
commentReducer
commentReducer,
tpiReducer
});

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 13:41:48
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 21:28:28
* @LastEditTime : 2020-01-02 14:24:09
*/
import types from "../actions/actionTypes";
import { Base64 } from 'js-base64';
@ -94,10 +94,11 @@ const ojForUserReducer = (state = initialState, action) => {
pages: Object.assign({}, state.pages, { total: records_count })
}
case types.SAVE_USER_CODE:
let curCode = Base64.encode(action.payload);
// console.log('save_user_code: ', action.payload);
// let curCode = Base64.encode(action.payload);
return {
...state,
userCode: curCode,
userCode: action.payload,
isUpdateCode: true,
}
case types.IS_UPDATE_CODE:
@ -136,7 +137,6 @@ const ojForUserReducer = (state = initialState, action) => {
} else {
curHack['code'] = '';
}
console.log(curHack);
return {
...state,
hack: Object.assign({}, state.hack, curHack),

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 16:40:32
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 20:00:26
* @LastEditTime : 2020-01-03 16:39:09
*/
import { Base64 } from 'js-base64';
import types from '../actions/actionTypes';
@ -15,10 +15,12 @@ const init = {
language: '',
description: '',
difficult: '',
category: '',
sub_discipline_id: '', // 方向
// category: '',
// openOrNot: 1,
timeLimit: 3
},
tag_discipline_id: [], // 知识点
ojFormValidate: {
name: {
validateStatus: '',
@ -36,14 +38,18 @@ const init = {
validateStatus: '',
errMsg: ''
},
category: {
validateStatus: '',
errMsg: ''
},
// category: {
// validateStatus: '',
// errMsg: ''
// },
// openOrNot: {
// validateStatus: '',
// errMsg: ''
// },
sub_discipline_id: {
validateStatus: '',
errMsg: ''
},
timeLimit: {
validateStatus: '',
errMsg: ''
@ -67,6 +73,8 @@ const init = {
testCodeStatus: 'default', // 调试代码状态 default(默认值) | loading(加载中) | loaded(加载完成) | userCase(用户自定义测试用例) | finish(测试完成)
openTestCodeIndex: [0], // 展开的测试用例: 数组, 当出错时,展开所有出错的测试用例, 默认展开第一个
isPublish: 0, // 是否是发布状态: 0 未发布 1 已发布
courseQuestions: [], // 课程题库
knowledges: [], // 知识点下拉值
}
const tcValidateObj = {
@ -127,10 +135,17 @@ const ojFormReducer = (state = initialState, action) => {
return returnState(state, ojForm, ojFormValidate);
case types.VALIDATE_OJ_CATEGORY:
return returnState(state, ojForm, ojFormValidate);
case types.VALIDATE_OJ_SUB_DISCIPLINE_ID:
return returnState(state, ojForm, ojFormValidate);
case types.VALIDATE_OJ_OPENORNOT:
return returnState(state, ojForm, ojFormValidate);
case types.VALIDATE_OJ_TIMELIMIT:
return returnState(state, ojForm, ojFormValidate);
case types.SAVE_TAG_DISCIPLINE_ID:
return {
...state,
tag_discipline_id: action.payload
}
case types.ADD_TEST_CASE:
const { testCase, tcValidate } = action.payload;
const tcArrs = state.testCases.concat([testCase]);
@ -174,7 +189,8 @@ const ojFormReducer = (state = initialState, action) => {
* 6. 更改测试用例状态
* 7. 添加测试用例验证
*/
const { code = '', description, language, name, hack_sets = [], time_limit, difficult, category, status } = action.payload;
const { code = '', description, language, name, hack_sets = [], time_limit, difficult, category, status, sub_discipline_id, tag_discipline_id } = action.payload;
const { courseQuestions } = state;
let desc = null;
try {
desc = JSON.parse(description)
@ -188,7 +204,8 @@ const ojFormReducer = (state = initialState, action) => {
difficult,
category,
openOrNot: 1,
timeLimit: time_limit
timeLimit: time_limit,
sub_discipline_id
};
// state.code = code; // 保存代码块值
let curPosition = 0;
@ -208,6 +225,18 @@ const ojFormReducer = (state = initialState, action) => {
} else if (Array.isArray(code)) {
cbcode = Base64.decode(code[code.length - 1]);
}
// console.log('++++>>>>>>>>>>>>>', courseQuestions);
let temp_knowledges = [];
courseQuestions.forEach(c => {
if (sub_discipline_id && c.sub_disciplines) {
c.sub_disciplines.forEach(sub => {
if (+sub.id === sub_discipline_id) {
temp_knowledges = sub.tag_disciplines || [];
}
});
}
});
// state.position = curPosition; // 计算下一个测试用例的位置值
return {
...state,
@ -218,7 +247,9 @@ const ojFormReducer = (state = initialState, action) => {
testCasesValidate: curTcValidates,
testCodeStatus: hack_sets.length > 0 ? 'userCase' : 'default',
isPublish: status,
showCode: cbcode
showCode: cbcode,
tag_discipline_id,
knowledges: temp_knowledges
}
case types.CHANGE_PUBLISH_VALUE:
return {
@ -301,11 +332,29 @@ const ojFormReducer = (state = initialState, action) => {
if (tIndex === -1) {
tempArr.push(action.payload);
}
console.log(tempArr);
// console.log(tempArr);
return {
...state,
openTestCodeIndex: tempArr
}
case types.GET_COURSE_QUESTION:
return {
...state,
courseQuestions: action.payload
}
case types.CHANGE_KNOWLEDGES: {
return {
...state,
knowledges: action.payload
}
}
case types.SET_OJ_INITIAL_VALUE:
const _p = action.payload;
return {
...state,
ojForm: Object.assign({}, state.ojForm, {difficult: _p.difficult, sub_discipline_id: _p.sub_discipline_id}),
tag_discipline_id: _p.tag_discipline_id || []
}
default:
return state;
}

@ -0,0 +1,36 @@
/*
* @Description:
* @Author: tangjiang
* @Github:
* @Date: 2020-01-03 10:24:31
* @LastEditors : tangjiang
* @LastEditTime : 2020-01-03 11:44:26
*/
import types from "../actions/actionTypes";
const initialState = {
showOrHide: false,
isCollapse: false, // 是否展开测试集
};
const tpiReducer = (state = initialState, action) => {
const { type, payload } = action;
switch (type) {
case types.SHOW_OR_HIDE_TPI_TEST_CASE:
return {
...state,
showOrHide: payload
}
case types.IS_COLLAPSE_TEST_CASE:
return {
...state,
isCollapse: payload
}
default:
return {
...state
}
}
}
export default tpiReducer;

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 10:55:38
* @LastEditors : tangjiang
* @LastEditTime : 2019-12-27 11:06:27
* @LastEditTime : 2019-12-30 09:44:56
*/
import axios from 'axios';
@ -142,4 +142,10 @@ export async function fetchUploadImageUrl (id) {
export async function fetchAddNotes (identifier, params) {
const url = `/myproblems/${identifier}/add_notes.json`;
return axios.post(url, params);
}
// 获取课程体系
export async function fetchQuestion (params) {
const url = `/disciplines.json`;
return axios.get(url, { params });
}
Loading…
Cancel
Save