diff --git a/app/controllers/admins/customers_controller.rb b/app/controllers/admins/customers_controller.rb index 80b01757b..8235bdb80 100644 --- a/app/controllers/admins/customers_controller.rb +++ b/app/controllers/admins/customers_controller.rb @@ -1,4 +1,5 @@ class Admins::CustomersController < Admins::BaseController + # skip_before_action :check_sign helper_method :current_partner def index diff --git a/app/controllers/concerns/git_helper.rb b/app/controllers/concerns/git_helper.rb index 085fec360..0d8604aac 100644 --- a/app/controllers/concerns/git_helper.rb +++ b/app/controllers/concerns/git_helper.rb @@ -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? diff --git a/app/controllers/partners_controller.rb b/app/controllers/partners_controller.rb index 7875e1780..dfa1b2017 100644 --- a/app/controllers/partners_controller.rb +++ b/app/controllers/partners_controller.rb @@ -1,4 +1,5 @@ class PartnersController < ApplicationController + skip_before_action :check_sign include Base::PaginateHelper include Admins::RenderHelper diff --git a/app/controllers/shixuns_controller.rb b/app/controllers/shixuns_controller.rb index 3de5970b6..7b3cb7588 100644 --- a/app/controllers/shixuns_controller.rb +++ b/app/controllers/shixuns_controller.rb @@ -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 diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a1f6a5495..c6dd7830c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -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 diff --git a/app/services/git_service.rb b/app/services/git_service.rb index 544e830a4..7867d063e 100644 --- a/app/services/git_service.rb +++ b/app/services/git_service.rb @@ -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 diff --git a/app/services/jupyter_service.rb b/app/services/jupyter_service.rb index 2d43a0987..bbe0330bb 100644 --- a/app/services/jupyter_service.rb +++ b/app/services/jupyter_service.rb @@ -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}" diff --git a/config/routes.rb b/config/routes.rb index 69d6d9377..2e860b0b0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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 diff --git a/public/images/educoder/bzucha.png b/public/images/educoder/bzucha.png new file mode 100755 index 000000000..d38b28cea Binary files /dev/null and b/public/images/educoder/bzucha.png differ diff --git a/public/images/educoder/zjzsd.png b/public/images/educoder/zjzsd.png new file mode 100755 index 000000000..d473966b2 Binary files /dev/null and b/public/images/educoder/zjzsd.png differ diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 9d856d899..94abb3740 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -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}`; diff --git a/public/react/src/common/UrlTool.js b/public/react/src/common/UrlTool.js index d50aef505..33c91fb89 100644 --- a/public/react/src/common/UrlTool.js +++ b/public/react/src/common/UrlTool.js @@ -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, """); return s; } + +export function publicSearchs(Placeholder,onSearch,onInputs,onChanges,loadings) { + return() +} \ No newline at end of file diff --git a/public/react/src/common/educoder.js b/public/react/src/common/educoder.js index 126a42e87..35abfc7fe 100644 --- a/public/react/src/common/educoder.js +++ b/public/react/src/common/educoder.js @@ -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'; diff --git a/public/react/src/common/quillForEditor/ImageBlot.js b/public/react/src/common/quillForEditor/ImageBlot.js index d00f2bafd..5ff84b249 100644 --- a/public/react/src/common/quillForEditor/ImageBlot.js +++ b/public/react/src/common/quillForEditor/ImageBlot.js @@ -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 { diff --git a/public/react/src/common/quillForEditor/index.js b/public/react/src/common/quillForEditor/index.js index cb214465c..f3f359a80 100644 --- a/public/react/src/common/quillForEditor/index.js +++ b/public/react/src/common/quillForEditor/index.js @@ -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); diff --git a/public/react/src/common/quillForEditor/index.scss b/public/react/src/common/quillForEditor/index.scss index 3e951e2b6..96cd45edd 100644 --- a/public/react/src/common/quillForEditor/index.scss +++ b/public/react/src/common/quillForEditor/index.scss @@ -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"; + } } \ No newline at end of file diff --git a/public/react/src/constants/index.js b/public/react/src/constants/index.js index 3e7aceab0..e9401e76e 100644 --- a/public/react/src/constants/index.js +++ b/public/react/src/constants/index.js @@ -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: '代码格式', diff --git a/public/react/src/modules/courses/Resource/Fileslistitem.js b/public/react/src/modules/courses/Resource/Fileslistitem.js index 99888e558..e7e31baab 100644 --- a/public/react/src/modules/courses/Resource/Fileslistitem.js +++ b/public/react/src/modules/courses/Resource/Fileslistitem.js @@ -253,22 +253,22 @@ class Fileslistitem extends Component{ {discussMessage.is_publish===false?:""} {this.props.isAdmin? - this.eventStop(event)}> - + this.eventStop(event)}> + this.settingList()}>设置 :""} {this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login? - this.eventStop(event)}> + this.eventStop(event)}> - + this.settingList()}>设置 - + this.onDelete(discussMessage.id)}>删除 @@ -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')} - {discussMessage&&discussMessage.category_name===null?"":this.props.child===false?
所属目录:{discussMessage&&discussMessage.category_name}
:""}

diff --git a/public/react/src/modules/courses/Resource/index.js b/public/react/src/modules/courses/Resource/index.js index ce4fb8dc2..501176882 100644 --- a/public/react/src/modules/courses/Resource/index.js +++ b/public/react/src/modules/courses/Resource/index.js @@ -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={ {/*{this.props.isAdmin()?parseInt(this.props.match.params.main_id)===parseInt(this.props.coursesids)?this.addDir()} className={"mr30 font-16"}>新建目录:"":""}*/} diff --git a/public/react/src/modules/courses/boards/index.js b/public/react/src/modules/courses/boards/index.js index 5cfbbeba3..ea49e862b 100644 --- a/public/react/src/modules/courses/boards/index.js +++ b/public/react/src/modules/courses/boards/index.js @@ -346,6 +346,7 @@ class Boards extends Component{ title={boardName || "帖子列表"} searchValue={ searchValue } onInputSearchChange={this.onInputSearchChange} + allowClearonChange={this.onInputSearchChange} showSearchInput={messages.length >= 10} searchPlaceholder={ '请输入帖子名称进行搜索' } firstRowRight={ diff --git a/public/react/src/modules/courses/busyWork/CommonWorkList.js b/public/react/src/modules/courses/busyWork/CommonWorkList.js index ca93833bb..35b2a1ee8 100644 --- a/public/react/src/modules/courses/busyWork/CommonWorkList.js +++ b/public/react/src/modules/courses/busyWork/CommonWorkList.js @@ -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} */}
- + {/**/} + {publicSearchs("请输入姓名或学号搜索",this.onSearchValue,this.onSearchValueInput,this.onSearchValueInput)}
} @@ -843,9 +855,9 @@ class CommonWorkList extends Component{
-

暂时还没有相关数据哦!

+

{searchtypes===true?"抱歉没有您要搜索的内容,请换个词语试试看":"暂时还没有相关数据哦!"}

) } diff --git a/public/react/src/modules/courses/coursesPublic/SelectSetting.js b/public/react/src/modules/courses/coursesPublic/SelectSetting.js index 1e177be3d..d96ae6f78 100644 --- a/public/react/src/modules/courses/coursesPublic/SelectSetting.js +++ b/public/react/src/modules/courses/coursesPublic/SelectSetting.js @@ -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) - } + }) } diff --git a/public/react/src/modules/courses/coursesPublic/sendResource.js b/public/react/src/modules/courses/coursesPublic/sendResource.js index e423340e7..cc7ecc03a 100644 --- a/public/react/src/modules/courses/coursesPublic/sendResource.js +++ b/public/react/src/modules/courses/coursesPublic/sendResource.js @@ -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) - } + }) } diff --git a/public/react/src/modules/courses/exercise/Exercise.js b/public/react/src/modules/courses/exercise/Exercise.js index dec8a1cff..faef2a531 100644 --- a/public/react/src/modules/courses/exercise/Exercise.js +++ b/public/react/src/modules/courses/exercise/Exercise.js @@ -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{ 未发布:{exercises_counts && exercises_counts.exercises_unpublish_counts}个

- + {publicSearchs("请输入名称进行搜索",this.searchInfo,this.inputStudent,this.inputStudent)} + {/**/}
diff --git a/public/react/src/modules/courses/graduation/tasks/index.js b/public/react/src/modules/courses/graduation/tasks/index.js index c316035ee..c10fdc5fc 100644 --- a/public/react/src/modules/courses/graduation/tasks/index.js +++ b/public/react/src/modules/courses/graduation/tasks/index.js @@ -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={ {/*{this.props.isAdmin() ? this.addDir()}>题库选用:""}*/} diff --git a/public/react/src/modules/courses/graduation/topics/index.js b/public/react/src/modules/courses/graduation/topics/index.js index b4bfa6527..b77b4c096 100644 --- a/public/react/src/modules/courses/graduation/topics/index.js +++ b/public/react/src/modules/courses/graduation/topics/index.js @@ -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 ? ( diff --git a/public/react/src/modules/courses/members/CourseGroupList.js b/public/react/src/modules/courses/members/CourseGroupList.js index 48bc2efcd..f489dac0a 100644 --- a/public/react/src/modules/courses/members/CourseGroupList.js +++ b/public/react/src/modules/courses/members/CourseGroupList.js @@ -136,6 +136,7 @@ function CourseGroupList(props) { title={"分班列表"} searchValue={ searchValue } onInputSearchChange={onInputSearchChange} + allowClearonChange={onInputSearchChange} showSearchInput={total_count >= 10} searchPlaceholder={ '请输入分班名称进行搜索' } firstRowRight={ diff --git a/public/react/src/modules/courses/poll/Poll.js b/public/react/src/modules/courses/poll/Poll.js index 447b454e4..dd0166e29 100644 --- a/public/react/src/modules/courses/poll/Poll.js +++ b/public/react/src/modules/courses/poll/Poll.js @@ -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{ 未发布:{polls_counts && polls_counts.polls_unpublish_counts}个

- + {publicSearchs("请输入名称进行搜索",this.searchInfo,this.inputStudent,this.inputStudent)} + {/**/}
diff --git a/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js b/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js index 879508ea1..0b760f7f9 100644 --- a/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js +++ b/public/react/src/modules/courses/shixunHomework/Listofworksstudentone.js @@ -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 {
: homework_status && homework_status.length === 0 ?
- +
: homework_status && homework_status.length > 0 && homework_status[0] === "未发布" ?
- +
:
@@ -3664,15 +3672,16 @@ class Listofworksstudentone extends Component { {/*}*/} {/*}*/} - this.onSearchKeywordKeyUpt(e)} - onInput={this.inputSearchValuest} - onSearch={this.searchValuest} - > + {/* this.onSearchKeywordKeyUpt(e)}*/} + {/* onInput={this.inputSearchValuest}*/} + {/* onSearch={this.searchValuest}*/} + {/*>*/} + {publicSearchs("请输入姓名或学号搜索",this.searchValuest,this.inputSearchValuest,this.inputSearchValuest)}
作品状态: @@ -3760,7 +3769,7 @@ class Listofworksstudentone extends Component {
-

暂时还没有相关数据哦!

+

{this.state.searchtypes===false?"暂时还没有相关数据哦!":"抱歉没有您要搜索的内容,请换个词语试试看"}

@@ -3769,9 +3778,9 @@ class Listofworksstudentone extends Component {
- {datajs === undefined ? "" : } + + {datajs === undefined ? "" :
} + + } @@ -3898,12 +3910,18 @@ class Listofworksstudentone extends Component { { homework_status && homework_status.length && homework_status.length === 0 ?
- +
: homework_status && homework_status.length > 0 && homework_status && homework_status[0] === "未发布" ?
- +
: @@ -4029,7 +4047,7 @@ class Listofworksstudentone extends Component {
-

暂时还没有相关数据哦!

+

{this.state.searchtypes===false?"暂时还没有相关数据哦!":"抱歉没有您要搜索的内容,请换个词语试试看"}

@@ -4069,12 +4087,18 @@ class Listofworksstudentone extends Component { { homework_status && homework_status.length === 0 ?
- +
: homework_status && homework_status.length > 0 && homework_status && homework_status[0] === "未发布" ?
- +
:
@@ -4226,9 +4250,9 @@ class Listofworksstudentone extends Component {
- {datas === undefined ? "" :
} + {datas === undefined ? "" : + +
+ + } { @@ -4270,7 +4298,7 @@ class Listofworksstudentone extends Component {
-

暂时还没有相关数据哦!

+

{this.state.searchtypes===false?"暂时还没有相关数据哦!":"抱歉没有您要搜索的内容,请换个词语试试看"}

diff --git a/public/react/src/modules/courses/shixunHomework/ShixunWorkReport.js b/public/react/src/modules/courses/shixunHomework/ShixunWorkReport.js index 90e6e6a4f..3765b2932 100644 --- a/public/react/src/modules/courses/shixunHomework/ShixunWorkReport.js +++ b/public/react/src/modules/courses/shixunHomework/ShixunWorkReport.js @@ -370,11 +370,11 @@ class ShixunWorkReport extends Component { {this.props.isAdmin() ?this.confirmysl(`/student_works/${homeworkid}/export_shixun_work_report.pdf`)} - > 导出实训报告数据: + > 导出实训报告: parseInt(this.props&&this.props.user.user_id)===parseInt(data&&data.user_id)?this.confirmysl(`/student_works/${homeworkid}/export_shixun_work_report.pdf`)} - > 导出实训报告数据:"" + > 导出实训报告:"" } {/*{this.props.isAdmin() ?work_comment_hidden===true? "":
-

{data&&data.username}

+

{data&&data.username}

-

- -

通过关卡: {data&&data.complete_count}/{data&&data.challenges_count}
+

+ +

当前完成关卡: {data&&data.complete_count}/{data&&data.challenges_count}
经验值: {data&&data.myself_experience}/{data&&data.total_experience}
-
课堂最高完成效率: {data&&data.max_efficiency===null?'--':data&&data.max_efficiency}
-
完成效率: {data&&data.efficiency===null?'--':data&&data.efficiency}
+
完成效率: {data&&data.efficiency===null?'--':data&&data.efficiency}
+
课堂最高完成效率: {data&&data.max_efficiency===null?'--':data&&data.max_efficiency}
通关时间: {data&&data.passed_time===null||data&&data.passed_time=== "--"?'--':moment(data&&data.passed_time).format('YYYY-MM-DD HH:mm')}
-
实战耗时: {data&&data.time_consuming===null?'--':data&&data.time_consuming}
+ {/*
实战耗时: {data&&data.time_consuming===null?'--':data&&data.time_consuming}
*/}

diff --git a/public/react/src/modules/courses/shixunHomework/Trainingjobsetting.js b/public/react/src/modules/courses/shixunHomework/Trainingjobsetting.js index d15e8eaab..2ce9c0e53 100644 --- a/public/react/src/modules/courses/shixunHomework/Trainingjobsetting.js +++ b/public/react/src/modules/courses/shixunHomework/Trainingjobsetting.js @@ -2671,14 +2671,14 @@ class Trainingjobsetting extends Component { className="ml15 font-14" style={{textAlign: "left", color: "#FF8204"}}>(总分值 = 效率分+ 关卡任务总分)
-
-
+
+
效率分(选中,则学生最终成绩包含效率分) + className={"font-13 color-grey-c ml15"} + style={{textAlign: "left"}}>(选中,则学生最终成绩包含效率分。效率分在作业截止或者补交结束后由系统自动生成)
@@ -2686,7 +2686,7 @@ class Trainingjobsetting extends Component {
-
+

diff --git a/public/react/src/modules/courses/shixunHomework/shixunHomework.js b/public/react/src/modules/courses/shixunHomework/shixunHomework.js index 4705e7a8f..d4a2d7b87 100644 --- a/public/react/src/modules/courses/shixunHomework/shixunHomework.js +++ b/public/react/src/modules/courses/shixunHomework/shixunHomework.js @@ -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( @@ -1212,12 +1213,15 @@ class ShixunHomework extends Component{

- this.SearchCoursename(value)} - > + {publicSearchs("请输入名称进行搜索",value => this.SearchCoursename(value),this.SearchCoursenames,(e)=>this.SearchCoursenames(e))} + {/* this.SearchCoursename(value)}*/} + {/* onChange={(e)=>this.allowClearonChange(e)}*/} + {/* allowClear={true}*/} + {/*>*/}
@@ -1380,14 +1384,3 @@ class ShixunHomework extends Component{ } } export default ShixunHomework; -// {/*
*/} -// {/*
*/} -// {/**/} -// {/*

暂时还没有相关数据哦!

*/} -// {/*
*/} \ No newline at end of file diff --git a/public/react/src/modules/courses/shixunHomework/shixunreport/ConclusionEvaluation.js b/public/react/src/modules/courses/shixunHomework/shixunreport/ConclusionEvaluation.js index 8d678f335..aa2da8594 100644 --- a/public/react/src/modules/courses/shixunHomework/shixunreport/ConclusionEvaluation.js +++ b/public/react/src/modules/courses/shixunHomework/shixunreport/ConclusionEvaluation.js @@ -66,7 +66,7 @@ class ConclusionEvaluation extends Component { ), },{ - title: '最终成绩', + title: '当前成绩', dataIndex: 'grade', key: 'grade', render: (text, record) => ( @@ -81,7 +81,7 @@ class ConclusionEvaluation extends Component { ), }, { - title: '实战耗时', + title: '实战总耗时', key: 'elapsed', dataIndex: 'elapsed', diff --git a/public/react/src/modules/developer/components/knowledge/index.js b/public/react/src/modules/developer/components/knowledge/index.js new file mode 100644 index 000000000..b287a42c9 --- /dev/null +++ b/public/react/src/modules/developer/components/knowledge/index.js @@ -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) => ( + + )); + } + // 过滤下拉列表项 + 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) => ( + + {item.name} + handleRemoveResult(item)} + className="iconfont icon-roundclose knowledge-close" + > + + )); + } + // 渲染下拉列表 + const renderSelect = (options = []) => { + // console.log('+++++', options); + // setSelectValue(_selects); + return ( + + ) + } + + return ( +
+ { renderSelect(selectOptions) } + {/* 渲染下拉选择项 */} +
+ { renderResult(selectValue) } +
+
+ ); +} + +export default KnowLedge; diff --git a/public/react/src/modules/developer/components/knowledge/index.scss b/public/react/src/modules/developer/components/knowledge/index.scss new file mode 100644 index 000000000..5bd0f5f61 --- /dev/null +++ b/public/react/src/modules/developer/components/knowledge/index.scss @@ -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; + } + } + } + } +} diff --git a/public/react/src/modules/developer/components/myMonacoEditor/index.js b/public/react/src/modules/developer/components/myMonacoEditor/index.js index b37770328..930561e37 100644 --- a/public/react/src/modules/developer/components/myMonacoEditor/index.js +++ b/public/react/src/modules/developer/components/myMonacoEditor/index.js @@ -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'; diff --git a/public/react/src/modules/developer/newOrEditTask/index.js b/public/react/src/modules/developer/newOrEditTask/index.js index 83200beac..eb894d1d0 100644 --- a/public/react/src/modules/developer/newOrEditTask/index.js +++ b/public/react/src/modules/developer/newOrEditTask/index.js @@ -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( diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js index d4fc12b9c..250437bcd 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js @@ -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 ( - + {name} ({subTitle}) @@ -161,7 +194,7 @@ class EditTab extends React.Component { ) } else { return ( - {name} + {name} ) } }; @@ -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 ( + + ) + } + + // 知识点 + const handleKnowledgeChange = (values= []) => { + const _result = []; + values.forEach(v => { + _result.push(v.id); + }); + console.log('下拉选择的值:===>>>', _result); + // 保存选择的知识点 + this.props.saveTagDisciplineId(_result); + } return (
@@ -262,16 +362,34 @@ class EditTab extends React.Component { {myLabel(jcLabel['category'], '合理的分类有利于快速检索')}} - validateStatus={ojFormValidate.category.validateStatus} - help={ojFormValidate.category.errMsg} + label={{myLabel(jcLabel['sub_discipline_id'], '合理的课程分类有利于快速检索')}} + validateStatus={ojFormValidate.sub_discipline_id.validateStatus} + help={ojFormValidate.sub_discipline_id.errMsg} colon={ false } > - {getOptions('category')} - + */} + {/* */} + { renderCourseQuestion(courseQuestions)} + {myLabel(jcLabel['knowledge'], '', 'nostar')}} + > + + + {myLabel(jcLabel['timeLimit'], '程序允许时间限制时长,单位:秒')}} @@ -317,16 +435,13 @@ class EditTab extends React.Component { help={ojFormValidate.description.errMsg} colon={ false } > -
- -
-
{/* { 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( diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss index 723678bb3..ff5df7090 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss @@ -18,6 +18,12 @@ line-height: 1; content: '*'; } + + &.nostar{ + &::before { + content: '' + } + } } .input_area{ display: inline-block; diff --git a/public/react/src/modules/developer/recordDetail/index.js b/public/react/src/modules/developer/recordDetail/index.js index fd93b3f2a..6675f066d 100644 --- a/public/react/src/modules/developer/recordDetail/index.js +++ b/public/react/src/modules/developer/recordDetail/index.js @@ -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); } } diff --git a/public/react/src/modules/developer/split_pane_resizer.scss b/public/react/src/modules/developer/split_pane_resizer.scss index 8fc8b525f..8d4ad171c 100644 --- a/public/react/src/modules/developer/split_pane_resizer.scss +++ b/public/react/src/modules/developer/split_pane_resizer.scss @@ -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; -} \ No newline at end of file +} diff --git a/public/react/src/modules/developer/studentStudy/leftpane/index.js b/public/react/src/modules/developer/studentStudy/leftpane/index.js index ac8d89321..88c5ee9a0 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/index.js @@ -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: (), comment: () }; - - console.log('======>>>>>>>', props); useEffect(() => { setDefaultActiveKey(userCodeTab); diff --git a/public/react/src/modules/developer/studentStudy/rightpane/index.js b/public/react/src/modules/developer/studentStudy/rightpane/index.js index ed500fb3a..bebaea1e8 100644 --- a/public/react/src/modules/developer/studentStudy/rightpane/index.js +++ b/public/react/src/modules/developer/studentStudy/rightpane/index.js @@ -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 (
+ {` /* 评测结果 */ .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 } - 测试集 + >测试集 */} {/*
{ + const { showOrHide, isCollapse } = state.tpiReducer; + return { + showOrHide, + isCollapse + } +}; + +export default connect( + mapStateToProps +)(VNCContainer); diff --git a/public/react/src/modules/page/main/CodeEvaluateView.js b/public/react/src/modules/page/main/CodeEvaluateView.js index 760ccd1ad..e70d02008 100644 --- a/public/react/src/modules/page/main/CodeEvaluateView.js +++ b/public/react/src/modules/page/main/CodeEvaluateView.js @@ -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 (
    @@ -312,17 +330,20 @@ class CodeEvaluateView extends Component {
  • this.tabIndexChange(1)}> 测试结果
  • - {/*
  • - - +
  • + this.handleShowTestCase()}> + -
  • */} + - {this.props.inDrawer ? + {this.props.inDrawer ? {/*TODO 按钮大小改造,css*/} {/* icon-guanbi */} - + {/* + */} + this.onHandleTestCase()}> + : @@ -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); diff --git a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css index 075a5af0f..a628787e5 100644 --- a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css +++ b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css @@ -160,7 +160,7 @@ .newyslusercjz{ display: inline-block; position: absolute; - bottom: 0px; + bottom: 10px; left: -18px; width: 44px; height: 18px; diff --git a/public/react/src/redux/actions/actionTypes.js b/public/react/src/redux/actions/actionTypes.js index 73e3ea0b2..53d62003b 100644 --- a/public/react/src/redux/actions/actionTypes.js +++ b/public/react/src/redux/actions/actionTypes.js @@ -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; diff --git a/public/react/src/redux/actions/index.js b/public/react/src/redux/actions/index.js index 988a0a469..efce336c9 100644 --- a/public/react/src/redux/actions/index.js +++ b/public/react/src/redux/actions/index.js @@ -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 } \ No newline at end of file diff --git a/public/react/src/redux/actions/ojForUser.js b/public/react/src/redux/actions/ojForUser.js index 45594631f..99c759996 100644 --- a/public/react/src/redux/actions/ojForUser.js +++ b/public/react/src/redux/actions/ojForUser.js @@ -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({ diff --git a/public/react/src/redux/actions/ojForm.js b/public/react/src/redux/actions/ojForm.js index 118295802..6d2da50a3 100644 --- a/public/react/src/redux/actions/ojForm.js +++ b/public/react/src/redux/actions/ojForm.js @@ -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 + } +} diff --git a/public/react/src/redux/actions/tpi.js b/public/react/src/redux/actions/tpi.js new file mode 100644 index 000000000..8fe134c32 --- /dev/null +++ b/public/react/src/redux/actions/tpi.js @@ -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 + } +} diff --git a/public/react/src/redux/reducers/index.js b/public/react/src/redux/reducers/index.js index 206f34384..7c9601d52 100644 --- a/public/react/src/redux/reducers/index.js +++ b/public/react/src/redux/reducers/index.js @@ -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 }); diff --git a/public/react/src/redux/reducers/ojForUserReducer.js b/public/react/src/redux/reducers/ojForUserReducer.js index 721c3e2cc..475d14d79 100644 --- a/public/react/src/redux/reducers/ojForUserReducer.js +++ b/public/react/src/redux/reducers/ojForUserReducer.js @@ -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), diff --git a/public/react/src/redux/reducers/ojFormReducer.js b/public/react/src/redux/reducers/ojFormReducer.js index 952919aca..95236b821 100644 --- a/public/react/src/redux/reducers/ojFormReducer.js +++ b/public/react/src/redux/reducers/ojFormReducer.js @@ -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; } diff --git a/public/react/src/redux/reducers/tpiReducer.js b/public/react/src/redux/reducers/tpiReducer.js new file mode 100644 index 000000000..d03ae3a4a --- /dev/null +++ b/public/react/src/redux/reducers/tpiReducer.js @@ -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; diff --git a/public/react/src/services/ojService.js b/public/react/src/services/ojService.js index 04fde2224..59151e687 100644 --- a/public/react/src/services/ojService.js +++ b/public/react/src/services/ojService.js @@ -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 }); } \ No newline at end of file