Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

newyslclassrooms
caicai8 5 years ago
commit 42d0b45c6e

@ -2,9 +2,13 @@ class CourseModulesController < ApplicationController
before_action :require_login, :check_auth
before_action :set_module, except: [:unhidden_modules]
before_action :find_course, only: [:unhidden_modules]
before_action :teacher_or_admin_allowed, except: [:add_second_category]
before_action :teacher_or_admin_allowed, except: [:show, :add_second_category]
before_action :teacher_allowed, only: [:add_second_category]
def show
end
# 模块置顶
def sticky_module
# position为1则不做处理否则该模块的position置为1position小于当前模块的position加1

@ -30,14 +30,14 @@ class CoursesController < ApplicationController
:informs, :update_informs, :online_learning, :update_task_position, :tasks_list,
:join_excellent_course, :export_couser_info, :export_member_act_score, :new_informs,
:delete_informs, :change_member_role, :course_groups, :join_course_group, :statistics,
:work_score, :act_score, :calculate_all_shixun_scores]
:work_score, :act_score, :calculate_all_shixun_scores, :move_to_category]
before_action :user_course_identity, except: [:join_excellent_course, :index, :create, :new, :apply_to_join_course,
:search_course_list, :get_historical_course_students, :mine, :search_slim, :board_list]
before_action :teacher_allowed, only: [:update, :destroy, :settings, :search_teacher_candidate,
:transfer_to_course_group, :delete_from_course, :export_member_scores_excel,
:search_users, :add_students_by_search, :get_historical_courses, :add_teacher_popup,
:add_teacher, :export_couser_info, :export_member_act_score,
:update_informs, :new_informs, :delete_informs, :switch_to_student]
:update_informs, :new_informs, :delete_informs, :switch_to_student, :move_to_category]
before_action :admin_allowed, only: [:set_invite_code_halt, :set_public_or_private, :change_course_admin,
:set_course_group, :create_group_by_importing_file,
:update_task_position, :tasks_list]
@ -118,6 +118,21 @@ class CoursesController < ApplicationController
render_ok
end
# 视频移动到目录
def move_to_category
tip_exception("请选择要移动的目录") if params[:new_category_id].blank?
category = @course.course_second_categories.find_by(id: params[:new_category_id])
if params[:new_category_id].to_i == 0 || category.present?
videos = @course.course_videos.where(id: params[:video_ids])
videos.update_all(course_second_category_id: params[:new_category_id])
normal_status(0, "操作成功")
else
normal_status(-1, "目录不存在")
end
end
def visits_plus_one
new_visits = @course.visits + 1
@course.update_visits(new_visits)
@ -1259,7 +1274,7 @@ class CoursesController < ApplicationController
@is_teacher = @user_course_identity < Course::ASSISTANT_PROFESSOR
@course_modules = @course.course_modules.where(hidden: 0)
@hidden_modules = @course.course_modules.where(hidden: 1)
@second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group"]
@second_category_type = ["shixun_homework", "graduation", "attachment", "board", "course_group", "video"]
end
def board_list

@ -13,7 +13,8 @@ class HackUserLastestCodesController < ApplicationController
end
def update_code
@my_hack.update_attribute(:code, params[:code])
# 防止tpm改动了语言所以更新语言字段
@my_hack.update_attributes(code: params[:code], language: @hack.language)
render_ok
end
@ -87,7 +88,7 @@ class HackUserLastestCodesController < ApplicationController
# 只有编译出错时,才正则匹配错误行数
error_line=
if ojEvaResult['status'] == "4" || ojEvaResult['status'] == "5"
regular_match_error_line ojEvaResult['outPut'], @my_hack.hack.language
regular_match_error_line ojEvaResult['outPut'], @hack.language
end
# debug 与submit 公用的参数
@ -100,7 +101,7 @@ class HackUserLastestCodesController < ApplicationController
if ojEvaResult['execMode'] == "debug"
save_debug_data ds_params
elsif ojEvaResult['execMode'] == "submit"
save_submit_data ds_params.merge(expected_output: testCase['expectedOutput'],
save_submit_data ds_params.merge(expected_output: testCase['expectedOutput'], language: @hack.language,
error_test_set_id: ojEvaResult['failCaseNum'])
end
# 评测完成后,还原评测中的状态
@ -138,7 +139,7 @@ class HackUserLastestCodesController < ApplicationController
debug_params = {execMode: exec_mode,
tpiID: @my_hack.identifier,
testCases: testCases,
platform: @my_hack.language,
platform: @my_hack.hack.language,
codeFileContent: @my_hack.code,
timeLimit: @hack.time_limit,
sec_key: Time.now.to_i}
@ -149,7 +150,7 @@ class HackUserLastestCodesController < ApplicationController
# 正则错误行数
def regular_match_error_line content, language
content = Base64.decode64(content).force_encoding("utf-8")
content = Base64.decode64(content) #.force_encoding("utf-8")
logger.info("######content: #{content}")
case language
when 'Java'

@ -6,7 +6,7 @@ class HomeworkCommonsController < ApplicationController
before_action :require_login, :check_auth, except: [:index, :choose_category]
before_action :find_course, only: [:index, :create, :new, :shixuns, :subjects, :create_shixun_homework, :publish_homework,
:end_homework, :set_public, :choose_category, :move_to_category, :choose_category,
:end_homework, :set_public, :move_to_category, :choose_category,
:create_subject_homework, :multi_destroy, :add_to_homework_bank]
before_action :find_homework, only: [:edit, :show, :update, :group_list, :homework_code_repeat, :code_review_results,
:code_review_detail, :show_comment, :settings, :works_list, :update_settings,

@ -87,16 +87,18 @@ module CoursesHelper
# 子目录对应的url
def category_url category, course
case category.category_type
when "shixun_homework"
"/courses/#{course.id}/shixun_homework/#{category.id}"
when "graduation"
if category.name == "毕设选题"
"/courses/#{course.id}/graduation_topics/#{category.course_module_id}"
else
"/courses/#{course.id}/graduation_tasks/#{category.course_module_id}"
end
when "attachment"
"/courses/#{course.id}/file/#{category.id}"
when "shixun_homework"
"/courses/#{course.id}/shixun_homework/#{category.id}"
when "graduation"
if category.name == "毕设选题"
"/courses/#{course.id}/graduation_topics/#{category.course_module_id}"
else
"/courses/#{course.id}/graduation_tasks/#{category.course_module_id}"
end
when "attachment"
"/courses/#{course.id}/file/#{category.id}"
when "video"
"/courses/#{course.id}/course_videos/#{category.id}"
end
end
@ -113,6 +115,8 @@ module CoursesHelper
end
when "attachment"
get_attachment_count(course, category.id)
when "video"
get_video_count(course, category.id)
end
end
@ -237,6 +241,11 @@ module CoursesHelper
category_id.to_i == 0 ? course.attachments.size : course.attachments.where(course_second_category_id: category_id).size
end
# 获取课堂的视频数
def get_video_count(course, category_id)
category_id.to_i == 0 ? course.course_videos.size : course.course_videos.where(course_second_category_id: category_id).size
end
# 获取课堂的作业数
def get_homework_commons_count(course, type, category_id)
category_id == 0 ? HomeworkCommon.where(course_id: course.id, homework_type: type).size :

@ -8,6 +8,8 @@ module AliyunVod::Service::VideoUpload
FileName: filename
}.merge(base_params)
# TODO 获取视频的同时,可以指定转码组,在这里指定
# 参数TemplateGroupId 转码组的id.
# 分类
cate_id = AliyunVod.cate_id
params[:CateId] = cate_id if cate_id.present?

@ -0,0 +1,8 @@
json.course_module do
json.id @course_module.id
json.module_name @course_module.module_name
json.module_type @course_module.module_type
json.course_second_categories do
json.array! @course_module.course_second_categories, :id, :name
end
end

@ -3,7 +3,7 @@ json.message "返回成功"
json.data do
json.(@hack_user, :id, :status, :error_line, :error_msg, :expected_output,
:input, :output, :execute_time, :execute_memory, :created_at, :code)
json.language @hack_user.hack.language
json.language @hack_user.language
json.name @hack_user.hack.name
json.myproblem_identifier @my_hack.identifier
json.pass_sets_count @pass_set_count

@ -1,7 +1,7 @@
json.records do
json.array! @records do |hack_user|
json.(hack_user, :id, :created_at, :status, :execute_time, :execute_memory)
json.language hack_user.hack.language
json.language hack_user.language
end
end

@ -524,6 +524,7 @@ Rails.application.routes.draw do
get 'statistics'
get 'course_videos'
delete 'delete_course_video'
post :move_to_category
post :inform_up
post :inform_down
get :calculate_all_shixun_scores

@ -0,0 +1,5 @@
class AddLanguageForHackUserCodes < ActiveRecord::Migration[5.2]
def change
add_column :hack_user_codes, :language, :string
end
end

@ -0,0 +1,5 @@
class AddCourseSecondCategoryIdToCourseVideos < ActiveRecord::Migration[5.2]
def change
add_column :course_videos, :course_second_category_id, :integer, index: true, default: 0
end
end

@ -2,12 +2,13 @@ desc "同步学院或者单位评测数"
namespace :sync_evaluate do
task outpus_count: :environment do
School.find_each do |school|
School.find_in_batches(batch_size: 50) do |school|
Parallel.each_with_index(school, in_processes: 5) do |s|
puts "school_id:#{s.id}"
evaluate_count = Game.find_by_sql("select sum(g.evaluate_count) as e_count from games g, user_extensions ue where
g.user_id = ue.user_id and ue.school_id = '#{s.id}'").first.try(:e_count)
puts "evaluate_count: #{evaluate_count}"
report = SchoolReport.find_or_initialize_by(school_id: s.id)
report.school_name = s.name
report.shixun_evaluate_count = evaluate_count

@ -77,7 +77,7 @@ const CONST = {
]
},
opacitySetting: {
title: '代码格式',
title: '快捷键',
type: 'label',
content: [
{

@ -372,13 +372,13 @@ class ShixunhomeWorkItem extends Component{
{this.props.isAdmin?<span onClick={(event)=>this.stopPro(event)} className={discussMessage&&discussMessage.shixun_status>1?this.props.isAdminOrCreator()?" newhomepagePostSettingname fr":" homepagePostSettingbox fr":" newwidthSettin fr"} style={{"right":"-2px","top":"6px","display":"block"}}>
{discussMessage&&discussMessage.shixun_status>1?<Link className="btn colorblue font-16 fontweight400 mr20" to={"/shixuns/"+discussMessage.shixun_identifier+"/challenges"} target={"_blank"}>进入学习</Link>:
<a className={"btn colorfff font-16 fontweight400 "}>进入学习</a>
{this.props.isAdmin?<span onClick={(event)=>this.stopPro(event)} className={discussMessage&&discussMessage.shixun_status>1?this.props.isAdminOrCreator()?" newhomepagePostSettingname fr":" mr20 fr":"fr mr20"} style={{"right":"-2px","top":"6px","display":"block"}}>
{discussMessage&&discussMessage.shixun_status>1?<Link className="btn colorblue font-16 fontweight400" to={"/shixuns/"+discussMessage.shixun_identifier+"/challenges"} target={"_blank"}>进入学习</Link>:
""
}
{this.props.isAdminOrCreator()?<a onClick={(event)=>this.editname(discussMessage.name,discussMessage.homework_id,event)} className={"btn colorblue font-16 fontweight400 "}>重命名</a>:""}
{this.props.isAdminOrCreator()?<a onClick={(event)=>this.editname(discussMessage.name,discussMessage.homework_id,event)} className={"ml20 btn colorblue font-16 fontweight400 "}>重命名</a>:""}
{/*<WordsBtn className="btn colorblue ml20 font-16" to={`/courses/${this.props.match.params.coursesId}/${this.state.shixuntypes}/${discussMessage.homework_id}/settings?tab=3`} > 设置</WordsBtn>*/}
<WordsBtn className="btn colorblue font-16 ml15 fontweight400 " to={`/courses/${this.props.match.params.coursesId}/${this.state.shixuntypes}/${discussMessage.homework_id}/settings?tab=3`} > 设置</WordsBtn>
</span>:""}
@ -433,7 +433,7 @@ class ShixunhomeWorkItem extends Component{
:
<span className="mr15 color-grey9">{discussMessage.status_time}</span>
}

@ -8,7 +8,7 @@
*/
import './index.scss';
import React, { useState, useRef, useEffect } from 'react';
import { Tabs, Button, Icon, notification } from 'antd';
import { Tabs, Button, Icon, notification } from 'antd';
import { connect } from 'react-redux';
import InitTabCtx from '../initTabCtx';
import ExecResult from '../execResult';
@ -17,14 +17,13 @@ import actions from '../../../../redux/actions';
const { TabPane } = Tabs;
const ControlSetting = (props) => {
const {
hack,
userCode,
const {
inputValue,
loading,
submitLoading,
identifier,
excuteState,
editor_code,
// showOrHideControl,
commitTestRecordDetail,
changeLoadingState,
@ -59,7 +58,7 @@ const ControlSetting = (props) => {
// 调试代码
const handleTestCode = (e) => {
if (!userCode) {
if (!editor_code) {
notification.warning({
message: '提示',
description: '代码块内容不能为空'
@ -74,11 +73,11 @@ const ControlSetting = (props) => {
setDefaultActiveKey('2');
});
}
// 提交
const handleSubmit = (e) => {
e.preventDefault();
if (!userCode) {
if (!editor_code) {
notification.warning({
message: '提示',
description: '代码块内容不能为空'
@ -103,56 +102,53 @@ const ControlSetting = (props) => {
return (
<div className="pane_control_area">
<div
className="pane_control_collapse"
className="pane_control_collapse"
onClick={handleShowControl}
style={{ top: showTextResult ? '-267px' : 0 }}
>
{/* <i className="iconfont icon-xiajiantou icon"></i> */}
<Icon type={ showTextResult ? "down" : "up" } />
<Icon type={showTextResult ? "down" : "up"} />
</div>
<Tabs
className={classNames}
activeKey={defaultActiveKey}
activeKey={defaultActiveKey}
tabBarStyle={{ backgroundColor: 'rgba(18,28,36,1)', color: '#fff' }}
onChange={handleTabChange}
>
<TabPane tab={'自定义测试用例'} key={'1'} style={{ height: '280px', overflowY: 'auto' }}>
<InitTabCtx
inputValue={inputValue}
<InitTabCtx
inputValue={inputValue}
wrappedComponentRef={(form) => formRef.current = form}
onDebuggerCode={handleDebuggerCode}
/>
</TabPane>
<TabPane tab={'代码执行结果'} key={'2'} style={{ height: '280px', overflowY: 'auto' }}>
<ExecResult
<ExecResult
excuteState={excuteState}
excuteDetail={commitTestRecordDetail}
/>
</TabPane>
</Tabs>
<div className="pane_control_opts">
<Button
type="link"
style={{ color: '#fff' }}
// onClick={handleShowControl}
<Button
type="link"
style={{ color: '#fff' }}
>
控制台
{/* <Icon type={ showTextResult ? "down" : "up" } /> */}
控制台
</Button>
<p>
<Button ghost
<Button ghost
loading={loading}
style={{ marginRight: '10px', color: '#28BD8B', borderColor: '#28BD8B' }}
style={{ marginRight: '10px', color: '#28BD8B', borderColor: '#28BD8B' }}
onClick={handleTestCode}
disabled={!identifier}
>调试代码</Button>
<Button
<Button
loading={submitLoading}
type="primary"
onClick={handleSubmit}
>
{/* {props.identifier ? '更新' : '提交'} */}
提交
>
提交
</Button>
</p>
</div>
@ -161,12 +157,12 @@ const ControlSetting = (props) => {
}
const mapStateToProps = (state) => {
const {commonReducer, ojForUserReducer} = state;
const {loading, excuteState, submitLoading, showOrHideControl } = commonReducer;
const { commitTestRecordDetail, hack, userCode } = ojForUserReducer;
const { commonReducer, ojForUserReducer } = state;
const { loading, excuteState, submitLoading, showOrHideControl } = commonReducer;
const { commitTestRecordDetail, hack, editor_code } = ojForUserReducer;
return {
hack,
userCode,
editor_code,
loading,
submitLoading,
excuteState,

@ -1,58 +1,67 @@
.tab_ctx_area{
.tab_ctx_area {
display: flex;
height: 100%;
color: #666;
font-size: 14px;
&.pos_start{
&.pos_start {
justify-content: flex-start;
}
&.pos_center{
&.pos_center {
justify-content: center;
align-items: center;
}
&.pos_end{
&.pos_end {
justify-content: flex-end;
}
.ctx_default{
.ctx_default {
margin: 10px 20px;
}
.ctx_loading,
.ctx_loaded{
.ctx_loaded {
display: flex;
position: relative;
flex-direction: column;
top: -20px;
color: #1890ff;
.ctx_icon{
.ctx_icon {
font-size: 40px;
margin-bottom: 10px;
}
}
}
.user_case_form{
.user_case_form {
display: flex;
align-items: flex-start;
margin-top: 20px;
.input_area{
padding-top: 20px;
.input_area {
flex: 1;
.ant-form-item-required{
.ant-form-item-required {
color: #fff;
}
}
.flex_l{
.flex_l {
padding: 0 10px 0 10px;
color: #fff;
}
.flex_r{
.flex_r {
padding: 0 20px 0 10px;
}
.input_textarea_style{
// background:rgba(30,30,30,1) !important;
background:rgba(7,15,25,1) !important;
.input_textarea_style {
background: rgba(7, 15, 25, 1) !important;
color: #fff;
border-color: transparent;
border: 0px solid transparent !important;
outline: none;
}
}
}

@ -11,7 +11,8 @@ import React, { useState, useRef, useEffect } from 'react';
import { Drawer, Tooltip, Badge } from 'antd';
import { fromStore, CNotificationHOC } from 'educoder';
import { connect } from 'react-redux';
import MonacoEditor from '@monaco-editor/react';
import { ControlledEditor } from '@monaco-editor/react';
import SettingDrawer from '../../components/monacoSetting';
import CONST from '../../../../constants';
import MyIcon from '../../../../common/components/MyIcon';
@ -47,8 +48,6 @@ function MyMonacoEditor(props, ref) {
return fromStore('oj_theme') || 'dark';
});
const [height, setHeight] = useState('calc(100% - 56px)');
const editorRef = useRef(null);
console.log(language, code, '-------========----------')
useEffect(() => {
setHeight(showOrHideControl ? 'calc(100% - 378px)' : 'calc(100% - 56px)');
@ -71,21 +70,10 @@ function MyMonacoEditor(props, ref) {
setTheme(value);
}
// 文本框内容变化时,记录文本框内容
const handleEditorChange = (_, monaco) => {
editorRef.current = monaco; // 获取当前monaco实例
}
useEffect(() => {
if (editorRef.current) {
editorRef.current.onDidChangeModelContent(e => { // 监听编辑器内容的变化
const val = editorRef.current.getValue();
onCodeChange(val);
});
}
}, [
editorRef.current
])
function onChangeHandler(ev, value) {
onCodeChange(value);
}
// 配置编辑器属性
const editorOptions = {
@ -152,17 +140,16 @@ function MyMonacoEditor(props, ref) {
<MyIcon className='code-icon' type="iconshezhi" onClick={handleShowDrawer} style={{ fontSize: '18px' }} />
</Tooltip>
</div>
<MonacoEditor
<ControlledEditor
height={height}
width="100%"
language={language && language.toLowerCase()}
value={code || ''}
options={editorOptions}
theme={theme} // dark || light
editorDidMount={handleEditorChange}
onChange={onChangeHandler}
/>
</div>
<Drawer
className={'setting_drawer'}
placement="right"
@ -176,6 +163,7 @@ function MyMonacoEditor(props, ref) {
/>
<SettingDrawer {...opacitySetting} />
</Drawer>
</React.Fragment>
)
};

@ -1,12 +1,19 @@
.user_case_form,
.excute_result_area {
background-color: rgba(7, 15, 25, 1);
}
.monaco_editor_area {
height: 100%;
background-color: rgba(7, 15, 25, 1);
.code_title {
display: flex;
align-items: center;
background-color: rgba(18, 28, 36, 1);
color: #fff;
height: 56px;
background-color: rgba(18, 28, 36, 1);
padding: 0 20px;
.flex_strict {
@ -30,6 +37,17 @@
}
}
// .margin,
// .margin-view-overlays,
// .current-line{
// width: 40px !important;
// }
// .monaco-editor .margin-view-overlays .line-numbers{
// text-align: center;
// }
// .monaco-scrollable-element{
// left: 40px !important;
// }
}
.setting_drawer {
@ -71,6 +89,13 @@
animation-iteration-count: 3;
}
// .monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input,
// .monaco-editor .margin,
// .minimap slider-mouseover,
// .minimap-decorations-layer{
// background:rgba(3,19,40,1) !important;
// }
@keyframes blink {
50% {
color: #fff;

@ -26,7 +26,7 @@ const { Option } = Select;
const maps = {
language: [
{ title: 'C', key: 'C' },
{ title: 'C++', key: 'C++' },
{ title: 'C++', key: 'cpp' },
{ title: 'Python', key: 'Python' },
{ title: 'Java', key: 'Java' }
],
@ -300,7 +300,6 @@ class EditTab extends React.Component {
{ 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': [] }, // 字体颜色与背景色

@ -108,18 +108,12 @@ function StudentStudy(props) {
return (
<div className={'student_study_warp'}>
<div className={'student_study_header'}>
{/* <div className={'avator_nicker'}>
<img alt="用户头像" className={'student_img'} src={getImageUrl((mygetHelmetapi && mygetHelmetapi.nav_logo_url) || 'images/educoder/headNavLogo.png?1526520218')} />
<span className={'student_nicker'}>
{(mygetHelmetapi &&mygetHelmetapi.name) || ''}
</span>
</div> */}
<UserInfo userInfo={userInfo} />
<div className={'study_name'}>
<span>{hack.name}</span>
</div>
<div className={'study_quit'}>
{/* to={`/problems/${_hack_id}/edit`} */}
<span
style={{ display: userInfo.hack_manager ? 'inline-block' : 'none' }}
onClick={() => handleClickEditor(hack.identifier)}
@ -127,16 +121,9 @@ function StudentStudy(props) {
>
<Icon type="form" className="quit-icon" /> 编辑
</span>
{/* to="/problems" */}
<span onClick={handleClickQuit} className="quit-btn">
<Icon type="poweroff" className="quit-icon" /> 退出
</span>
{/* <Button type="link" icon="form" className='quit-btn'>
<Link to="/problems">编辑</Link>
</Button>
<Button type="link" icon="poweroff" className='quit-btn'>
<Link to="/problems">退出</Link>
</Button> */}
</div>
</div>
<div className="split-pane-area">

@ -19,7 +19,7 @@ import ErrorResult from '../../../components/errorResult';
const numberal = require('numeral');
const {reviewResult} = CONST;
const { reviewResult } = CONST;
// 表格列
const columns = [
{
@ -35,7 +35,7 @@ const columns = [
dataIndex: 'status',
render: (value, record) => (
<Link to={`/myproblems/record_detail/${record.id}`}>
<span style={{ color: value === 0 ? '#28BD8B' : '#E6262E'}}>{reviewResult[value]}</span>
<span style={{ color: value === 0 ? '#28BD8B' : '#E6262E' }}>{reviewResult[value]}</span>
</Link>
)
},
@ -72,28 +72,18 @@ const CommitRecord = (props) => {
identifier,
pages,
commitRecord,
// excuteState,
language,
operateType,
commitRecordDetail,
getUserCommitRecord,
changeRecordPagination
} = props;
const [current, setCurrent] = useState(1);
// const [pagination, setPagination] = useState(paginationConfig);
// const [tableData, setTableData] = useState([]);
const [current, setCurrent] = useState(pages.page);
// 复制面板
let clipboard;
// const [recordDetail, setRecordDetail] = useState({});
// const [renderCtx, setRenderCtx] = useState(() => {
// return function () {
// return '';
// }
// });
// 渲染提交记录详情
const renderRecordDetail = (commitRecordDetail = {}) => {
const {id, status} = commitRecordDetail;
const { id, status } = commitRecordDetail;
if (Object.keys(commitRecordDetail).length > 0) {
// console.log('当前状态====》》》', status);
const classes = status === 0 ? 'record_result_suc' : 'record_result_err';
@ -105,22 +95,22 @@ const CommitRecord = (props) => {
<p className={'record_result'}>
执行结果: <span className={classes}>{reviewResult[status]}</span>
</p>
<p
<p
id="copyError"
onClick={clickCopyErrInfo}
className={showErrorCopy} data-clipboard-target="#errcode">
<span>
复制错误信息 <Icon type="copy" className={'icon_style'}/>
复制错误信息 <Icon type="copy" className={'icon_style'} />
</span>
</p>
<p className={'show_detail'} style={{ visibility: id ? 'visible' : 'hidden' }}>
<Link to={`/myproblems/record_detail/${id}`}>
显示详情 <Icon type="right" className={'icon_style'}/>
显示详情 <Icon type="right" className={'icon_style'} />
</Link>
</p>
</div>
<div id="errcode" className={showErrorCode}>
<ErrorResult detail={commitRecordDetail} language={language}/>
<ErrorResult detail={commitRecordDetail} language={language} />
</div>
</React.Fragment>
);
@ -131,7 +121,7 @@ const CommitRecord = (props) => {
// 根据id获取用户提交记录
useEffect(() => {
getUserCommitRecord(identifier);
}, []);
}, [identifier]);
// 提交记录变化时,同步到表单数据
// useEffect(() => {
// // const len = commitRecord.length;
@ -149,9 +139,9 @@ const CommitRecord = (props) => {
// 复制功能
let count = 0;
// useEffect(() => {
// }, []);
const clickCopyErrInfo = () => {
count = 0;
if (!clipboard) {
@ -174,76 +164,27 @@ const CommitRecord = (props) => {
changeRecordPagination(page);
// 调用查询接口
getUserCommitRecord(identifier);
// setPagination(Object.assign({}, pagination, { current: page}));
// console.log('======>>>>>>', pagination)
}
// console.log(commitRecord);
const _style = {
display: pages.total > pages.limit ? 'block' : 'none'
};
const {status, id} = commitRecordDetail || {};
const classes = status === 0 ? 'record_result_suc' : 'record_result_err';
const showErrorCode = status !== 0 ? `ecord_error_info show_error_code` : `ecord_error_info`;
const showErrorCopy = status !== 0 ? `copy_error show_error_copy` : `copy_error`;
// if (!clipboard) {
// console.log('==========>>>>>>>', 11111111111);
// clipboard = new ClipboardJS('#copyError');
// }
// clipboard.on('success', (e) => {
// e.clearSelection();
// // if (count > 0) return;
// // count++;
// message.success('复制成功');
// setTimeout(() => {
// message.destroy();
// }, 3000);
// });
// return () => {
// clipboard = null;
// }
return (
<div className={'commit_record_area'}>
{renderRecordDetail(commitRecordDetail)}
{/* <div className={'record_header'}>
<p className={'record_result'}>
执行结果: <span className={classes}>{reviewResult[status]}</span>
</p>
<p
id="copyError"
onClick={clickCopyErrInfo}
className={showErrorCopy} data-clipboard-target="#errcode">
<span>
复制错误信息 <Icon type="copy" className={'icon_style'}/>
</span>
</p>
<p className={'show_detail'} style={{ visibility: id ? 'visible' : 'hidden' }}>
<Link to={`/myproblems/record_detail/${id}`}>
显示详情 <Icon type="right" className={'icon_style'}/>
</Link>
</p>
</div>
<div id="errcode" className={showErrorCode}>
<ErrorResult detail={commitRecordDetail} language={language}/>
</div> */}
<div className="commit_record_table_pagination">
<Table
<Table
columns={columns}
rowKey={function (record) { return `key_${record.id}`}}
rowKey={function (record) { return `key_${record.id}` }}
dataSource={commitRecord}
// pagination={pagination}
// onChange={handleTableChange}
pagination={false}
/>
<div className="commit_record_pagination" style={_style}>
<Pagination
<Pagination
showQuickJumper
pageSize={pages.limit}
current={current}
current={current}
total={pages.total}
onChange={handlePaginationChange}
/>

@ -57,7 +57,7 @@ const RightPane = (props) => {
timer = setInterval(function () {
clearInterval(timer);
timer = null;
saveUserCodeForInterval(identifier);
saveUserCodeForInterval(identifier, value);
}, 5000);
}
}
@ -99,13 +99,17 @@ const RightPane = (props) => {
});
}
const { getFieldDecorator } = props.form;
let language = hack.language
if (language === 'C++') {
language = 'cpp'
}
return (
<div className={'right_pane_code_wrap'}>
<MyMonacoEditor
notice={notice}
identifier={identifier}
language={hack.language}
language={language}
code={editor_code || hack.code}
hadCodeUpdate={hadCodeUpdate}
onCodeChange={handleCodeChange}
@ -118,9 +122,6 @@ const RightPane = (props) => {
onClick={handleClickNote}
></span>
{/* <div className="student_notes">
<TextArea rows={5} />
</div> */}
<div className={noteClazz}>
<Form>
<FormItem>

@ -102,13 +102,12 @@ export const getUserProgramDetail = (identifier, type) => {
export const saveUserCodeForInterval = (identifier, code) => {
return (dispatch, getState) => {
const { userCode } = getState().ojForUserReducer;
dispatch({
type: types.AUTO_UPDATE_CODE,
payload: true
});
fetchUpdateCode(identifier, {
code: Base64.encode(userCode)
code: Base64.encode(code)
}).then(res => {
if (res.data.status === 401) {
return;
@ -134,29 +133,28 @@ export const saveUserCodeForInterval = (identifier, code) => {
* @param {*} inputValue 输入值: 自定义 | 系统返回的
* @param {*} type 测评类型 debug | submit
*/
//原来的方法未能区分从编辑入口进来的情况,这时代码也是更新了的。
export const updateCode = (identifier, inputValue, type) => {
console.log(1111);
return (dispatch, getState) => {
const { userCode, isUpdateCode } = getState().ojForUserReducer;
const { editor_code, isUpdateCode } = getState().ojForUserReducer;
if (isUpdateCode) {
fetchUpdateCode(identifier, {
code: Base64.encode(userCode)
code: Base64.encode(editor_code)
}).then(res => {
// 是否更新了代码, 目的是当代码没有更新时不调用更新代码接口,目录没有实现
// TODO 需要优化
if (res.data.status === 401) {
dispatch({ // 改变 loading 值
type: types.LOADING_STATUS,
payload: false
if (res) {
if (res.data.status === 401) {
dispatch({ // 改变 loading 值
type: types.LOADING_STATUS,
payload: false
});
return;
};
dispatch({
type: types.IS_UPDATE_CODE,
flag: false
});
return;
};
dispatch({
type: types.IS_UPDATE_CODE,
flag: false
});
// debuggerCode(identifier, inputValue);
dispatch(debuggerCode(identifier, inputValue, type));
dispatch(debuggerCode(identifier, inputValue, type));
}
});
} else {
// 没有更新时,直接调用调试接口
@ -394,8 +392,7 @@ export const changeUserCodeTab = (key) => {
*/
export const submitUserCode = (identifier, inputValue, type) => {
return (dispatch, getState) => {
const { userCode, isUpdateCode, hack } = getState().ojForUserReducer;
const { editor_code, isUpdateCode, hack } = getState().ojForUserReducer;
function userCodeSubmit() {
fetchUserCodeSubmit(identifier).then(res => {
if (res.status === 200) {
@ -418,7 +415,7 @@ export const submitUserCode = (identifier, inputValue, type) => {
}
if (isUpdateCode) {
fetchUpdateCode(identifier, {
code: Base64.encode(userCode)
code: Base64.encode(editor_code)
}).then(res => {
// 是否更新了代码, 目的是当代码没有更新时不调用更新代码接口,目录没有实现
if (res.data.status === 401) {

@ -132,6 +132,7 @@ export const validateOjForm = (props, type, cb) => {
}
});
// 验证测试用例中的数组是否都有对应的值
let tcbool=false;
const tcValidResult = [];
// 验证测试用例: 1.必须要有输出值 2. 输入值与输出值必须唯一
testCases.forEach((obj, i) => {
@ -141,8 +142,25 @@ export const validateOjForm = (props, type, cb) => {
// 非空校验
let validateResult = emptyValidate(key, value);
const errMsg = validateResult[key].errMsg;
if (errMsg) {
// hasSuccess = false;
// console.log("-------");
// console.log(errMsg);
// console.log(key);
// console.log(value);
if (errMsg) {
if(key==="output"){
hasSuccess = false;
if(tcbool===false){
tcbool=true
notification['error']({
message: '提示',
description: '测试用例必须填写输出!'
});
}
}
} else {
// 唯一性校验
const bool = testCases.some((item, j) => {
@ -167,39 +185,7 @@ export const validateOjForm = (props, type, cb) => {
});
tcValidResult.push(tempObj);
});
try {
if(ojForm.sub_discipline_id.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '课程必须选择!'
});
}else if(ojForm.timeLimit===null){
hasSuccess = false;
notification['error']({
message: '提示',
description: '时间限制必须输入!'
});
} else if(ojForm.name.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '任务名称必须输入!'
});
}else if(ojForm.description.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '描述必须输入!'
});
}
}catch (e) {
}
// if (testCases.length === 0) {
// hasSuccess = false;
@ -234,6 +220,43 @@ export const validateOjForm = (props, type, cb) => {
payload: false
});
}
try {
if(ojForm.sub_discipline_id.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '课程必须选择!'
});
}else if(ojForm.timeLimit===null){
hasSuccess = false;
notification['error']({
message: '提示',
description: '时间限制必须输入!'
});
} else if(ojForm.name.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '任务名称必须输入!'
});
}else if(ojForm.description.length===0){
hasSuccess = false;
notification['error']({
message: '提示',
description: '描述必须输入!'
});
}
}catch (e) {
}
/** 表单验证结束 */
/** 表单验证通过后,调用保存 or 更新 or 发布 */
if (hasSuccess) {

@ -98,7 +98,7 @@ const ojForUserReducer = (state = initialState, action) => {
// let curCode = Base64.encode(action.payload);
return {
...state,
userCode: action.payload,
editor_code: action.payload,
isUpdateCode: true,
}
case types.IS_UPDATE_CODE:
@ -151,7 +151,8 @@ const ojForUserReducer = (state = initialState, action) => {
case types.SAVE_EDITOR_CODE:
return {
...state,
editor_code: action.payload
editor_code: action.payload,
isUpdateCode: true
}
case types.SAVE_USE_TEST_CASE_VALUE:
return {

Loading…
Cancel
Save