Merge remote-tracking branch 'origin/dev_aliyun' into dev_aliyun

chromesetting
杨树明 5 years ago
commit 2d78dfa16b

@ -25,7 +25,7 @@ class ShixunSearchService < ApplicationService
else
none_shixun_ids = ShixunSchool.where("school_id != #{User.current.school_id}").pluck(:shixun_id)
@shixuns = @shixuns.where.not(id: none_shixun_ids).where(hidden: 0, status: 2, public: 2).or(@shixuns.where(id: current_user.shixuns))
@shixuns = @shixuns.where.not(id: none_shixun_ids).where(hidden: 0, status: 2, public: 2).or(@shixuns.where(id: User.current.shixuns))
end
end

@ -0,0 +1,30 @@
/*
* @Description:
* @Author: tangjiang
* @Github:
* @Date: 2019-12-13 10:28:15
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-13 10:37:17
*/
import { Modal } from 'antd';
export function ModalConfirm (
title,
content,
handleOk,
handleCancel
) {
Modal.confirm({
title,
content,
okText: '确定',
cancelText: '取消',
onOk () {
handleOk && handleOk();
},
onCancel () {
handleCancel && handleCancel();
}
});
}

@ -44,6 +44,13 @@ const maps = {
'value': '2'
}
],
'languageMenu': [
{
'key': 'c',
'name': 'C语言',
'value': 'c'
}
],
'difficultMenu': [
{
'key': '1',
@ -119,15 +126,14 @@ class DeveloperHome extends React.PureComponent {
>
{/* <Link to={`/problems/${record.identifier}/edit`}></Link> */}
</Button>
<Button
<Button
shape="circle"
type="danger"
icon="close"
size="small"
style={{ marginLeft: '10px' }}
style={{ marginLeft: '10px', display: record.open_or_not ? 'none' : 'inline-block' }}
onClick={() => this.handleClickDelete(record)}
>
{/* <Link to={`/problems/${record.identifier}/edit`}></Link> */}
</Button>
</React.Fragment>
),
@ -197,7 +203,6 @@ class DeveloperHome extends React.PureComponent {
componentDidMount() {
// 是否是我的,如果是我的 显示编辑按钮
const { isMySource } = this.props;
console.log(this.props);
if (isMySource) {
this.handleFilterSearch({come_from: 'mine'});
let _columns = this.columns.concat([this.options]);
@ -346,6 +351,14 @@ class DeveloperHome extends React.PureComponent {
});
this.handleFilterSearch({category: +item.key === 0 ? '' : +item.key});
}
// 下拉语言
handleLanguageMenuClick = (item) => {
this.addShowFilterCtx({
type: 'language',
key: item.key
});
this.handleFilterSearch({language: item.key})
}
// 难度下拉
handleHardMenuClick = (item) => {
this.addShowFilterCtx({
@ -421,6 +434,7 @@ class DeveloperHome extends React.PureComponent {
// const { testReducer, handleClick } = this.props;
const {
ojListReducer: {hacks_list, top_data, hacks_count},
user,
pagination
} = this.props;
const {passed_count = 0, simple_count = 0, medium_count = 0, diff_count = 0} = top_data;
@ -443,7 +457,11 @@ class DeveloperHome extends React.PureComponent {
>{ctx}</Tag>
)});
};
// console.log('=====>>>>>>>>>.', this.props);
const newBtnStyle = user && (user.admin || (user.is_teacher && user.professional_certification) || user.business)
? { display: 'block'}
: { display: 'none'};
return (
<div className="developer-list">
<div className="ant-spin-container">
@ -457,7 +475,8 @@ class DeveloperHome extends React.PureComponent {
<MultipTags type="warning" text="中等" numb={medium_count} style={{ marginRight: '20px' }}/>
<MultipTags type="error" text="困难" numb={diff_count}/>
</div>
<Button type="primary" onClick={this.handleClickNew}>新建
{/* 认证的老师, 超级管理员, 运营人员可见 */}
<Button style={ newBtnStyle } type="primary" onClick={this.handleClickNew}>新建
{/* <Link to="/problems/new">新建</Link> */}
</Button>
</div>
@ -468,6 +487,9 @@ class DeveloperHome extends React.PureComponent {
<Dropdown className={'dropdonw-style'} placement="bottomLeft" overlay={this.getMenuItems('categoryMenu', this.handleCategoryMenuClick)}>
<span className={'dropdown-span'}>分类 <Icon type="down"/></span>
</Dropdown>
<Dropdown className={'dropdonw-style'} placement="bottomLeft" overlay={this.getMenuItems('languageMenu', this.handleLanguageMenuClick)}>
<span className={'dropdown-span'}>语言 <Icon type="down"/></span>
</Dropdown>
<Dropdown className={'dropdonw-style'} placement="bottomLeft" overlay={this.getMenuItems('difficultMenu', this.handleHardMenuClick)}>
<span className={'dropdown-span'}>难度 <Icon type="down"/></span>
</Dropdown>

@ -9,7 +9,7 @@ import './index.scss';
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import SplitPane from 'react-split-pane';// import { Form } from 'antd';
import { Button } from 'antd';
import { Button, Modal } from 'antd';
import LeftPane from './leftpane';
import RightPane from './rightpane';
import { withRouter } from 'react-router';
@ -17,6 +17,7 @@ import { toStore } from 'educoder';
import UserInfo from '../components/userInfo';
// import RightPane from './rightpane/index';
import actions from '../../../redux/actions';
import {ModalConfirm} from '../../../common/components/ModalConfirm';
const NewOrEditTask = (props) => {
const {
@ -32,17 +33,18 @@ const NewOrEditTask = (props) => {
changePublishLoadingStatus,
startProgramQuestion,
getUserInfoForNew,
handleCancelPublish,
// updateTestAndValidate,
} = props;
// 表单提交
const handleSubmitForm = () => {
// 改变loading状态
changeSubmitLoadingStatus(true);
// 调用输入表单验证功能
if (props.identifier) {
props.handleUpdateOjForm(props);
} else {
// 改变loading状态
changeSubmitLoadingStatus(true);
props.handleFormSubmit(props); // 提交表单
}
};
@ -66,6 +68,9 @@ const NewOrEditTask = (props) => {
}, []);
// 模拟挑战
const imitationChallenge = () => {
}
// 开始挑战
const startChallenge = () => {
// 调用 start 接口, 成功后跳转到模拟页面
startProgramQuestion(identifier, props);
@ -84,9 +89,20 @@ const NewOrEditTask = (props) => {
// 发布
const handleClickPublish = () => {
// console.log('public has click');
changePublishLoadingStatus(true);
handlePublish(props, 'publish');
ModalConfirm('提示', (<p>发布后即可应用到自己管理的课堂<br /> 是否确认发布?</p>), () => {
changePublishLoadingStatus(true);
handlePublish(props, 'publish');
});
}
// 撤销发布
const handleClickCancelPublish = () => {
ModalConfirm('提示', (<p>是否确认撤销发布?</p>), () => {
changePublishLoadingStatus(true);
handleCancelPublish(props, identifier);
});
}
// 取消保存/取消按钮
@ -107,20 +123,43 @@ const NewOrEditTask = (props) => {
}
// 发布/模拟挑战
const renderPubOrFight = () => {
const pubButton = isPublish ? '' : (<Button
type="primary"
loading={publishLoading}
onClick={handleClickPublish}
>立即发布</Button>);
const pubButton = isPublish
? (<Button
type="primary"
loading={publishLoading}
onClick={handleClickCancelPublish}
>撤销发布</Button>)
: (<Button
type="primary"
loading={publishLoading}
onClick={handleClickPublish}
>立即发布</Button>);
// 未发布: 模拟挑战 已发布: 开始挑战
const challengeBtn = isPublish ? (
<Button type="primary" onClick={startChallenge}>开始挑战</Button>
) : (
<Button type="primary" onClick={imitationChallenge}>模拟挑战</Button>
);
// 更新
// const updateBtn = isPublish
// ? ''
// : (
// <Button
// type="primary"
// loading={submitLoading}
// onClick={handleSubmitForm}
// >更新</Button>
// );
return (
<React.Fragment>
<Button
type="primary"
loading={submitLoading}
onClick={handleSubmitForm}
>更新</Button>
<Button
type="primary"
loading={submitLoading}
onClick={handleSubmitForm}
>更新</Button>
{pubButton}
<Button type="primary" onClick={startChallenge}>模拟挑战</Button>
{challengeBtn}
</React.Fragment>
)
}
@ -142,24 +181,9 @@ const NewOrEditTask = (props) => {
return (
<div className={'new_add_task_wrap'}>
<div className={'task_header'}>
{/* <Link to="/problems" className={'header_btn'} >
<Icon type="left" style={{ marginRight: '5px'}}/>后退
</Link> */}
<UserInfo userInfo={userInfo}/>
<p className={'header_title'}>{props.name || ''}</p>
{ renderQuit() }
{/* <Link style={{
position: 'absolute',
right: '30px',
top: 0,
color: '#5091FF'
}} to="/problems">退出</Link> */}
{/* <Button
style={{ display: identifier ? 'none' : 'block'}}
loading={publishLoading}
className={`header_btn`}
type="primary"
onClick={handleClickPublish}>立即发布</Button> */}
</div>
<div className="split-pane-area">
<SplitPane split="vertical" minSize={350} maxSize={-350} defaultSize="40%">
@ -206,6 +230,8 @@ const mapDispatchToProps = (dispatch) => ({
handleFormSubmit: (props) => dispatch(actions.validateOjForm(props)),
// 发布表单
handlePublish: (props, type) => dispatch(actions.validateOjForm(props, type)),
// 撤销发布
handleCancelPublish: (props, identifier) => dispatch(actions.handleClickCancelPublish(props, identifier)),
// 更新OJForm
handleUpdateOjForm: (props) => dispatch(actions.validateOjForm(props)),
// 根据id号获取表单信息

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-21 09:19:38
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 19:37:35
* @LastEditTime: 2019-12-13 11:58:46
*/
import './index.scss';
import React, { useState } from 'react';
@ -16,7 +16,7 @@ const { TextArea } = Input;
const FormItem = Form.Item;
const AddTestDemo = (props) => {
const {
// key,
key,
onSubmitTest,
onDeleteTest,
testCase,
@ -138,7 +138,7 @@ const AddTestDemo = (props) => {
return (
<Collapse className={'collapse_area'} activeKey={isOpen?'1':''} onChange={() => handleChangeCollapse()}>
<Panel header={`测试用例${testCase.position}`} extra={genExtra()} key="1">
<Panel header={`测试用例${props.index + 1}`} extra={genExtra()} key="1">
<Form>
<FormItem
label={<span className={'label_text'}>输入</span>}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 10:35:40
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-09 10:22:03
* @LastEditTime: 2019-12-13 11:39:52
*/
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.bubble.css';
@ -185,6 +185,7 @@ class EditTab extends React.Component {
};
const renderTestCase = () => {
return this.props.testCases.map((item, i) => {
console.log(111);
return <AddTestDemo
key={`${i}`}
isOpen={openTestCodeIndex.includes(i)}

@ -4,10 +4,10 @@
* @Github:
* @Date: 2019-11-23 10:53:19
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 19:16:18
* @LastEditTime: 2019-12-12 19:08:24
*/
import './index.scss';
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import SplitPane from 'react-split-pane';
import LeftPane from './leftpane';
@ -15,18 +15,22 @@ import RightPane from './rightpane';
// import { Link } from 'react-router-dom';
// import { getImageUrl } from 'educoder'
// import RightPane from '../newOrEditTask/rightpane';
import { Icon } from 'antd';
import { Icon, Modal } from 'antd';
import UserInfo from '../components/userInfo';
import actions from '../../../redux/actions';
import { fromStore} from 'educoder';
import { withRouter } from 'react-router';
const StudentStudy = (props) => {
function StudentStudy (props) {
const {
userInfo,
hack_identifier
} = props;
// 是否更新
const [isUpdate, setIsUpdate] = useState(true);
useEffect(() => {
const {
match: { params },
@ -35,13 +39,53 @@ const StudentStudy = (props) => {
} = props;
let { id } = params;
// console.log(id);
// 保存当前的id
saveUserProgramIdentifier(id);
// startProgramQuestion(id);
getUserProgramDetail(id);
}, []);
useEffect(() => {
console.log('=======>>>>>>>>');
const { hack = {} } = props;
if (!hack.modify_code && isUpdate) { // 代码更改,提示是否需要更新代码
setIsUpdate(false);
Modal.confirm({
title: '提示',
content: (
<p>
代码文件有更新啦 <br />
还未提交的代码请自行保存
</p>
),
okText: '立即更新',
cancelText: '稍后再说',
onOk () {
console.log('更新代码....');
}
});
}
}, [props]);
// useEffect(() => {
// const {hack} = props;
// if (!hack.modify_code) { // 代码更改,提示是否需要更新代码
// Modal.confirm({
// title: '提示',
// content: (
// <p>
// 代码文件有更新啦 <br />
// 还未提交的代码,请自行保存
// </p>
// ),
// okText: '立即更新',
// cancelText: '稍后再说',
// onOk () {
// console.log('更新代码....');
// }
// });
// }
// }, [props]);
const _hack_id = hack_identifier || fromStore('hack_identifier');
// 处理编辑
@ -70,7 +114,7 @@ const StudentStudy = (props) => {
</div>
<div className={'study_quit'}>
{/* to={`/problems/${_hack_id}/edit`} */}
<span onClick={handleClickEditor} className="quit-btn">
<span onClick={handleClickEditor} className={`quit-btn`}>
<Icon type="form" className="quit-icon"/> 编辑
</span>
{/* to="/problems" */}

@ -31,6 +31,7 @@ import {
testCaseOutputChange,
updateTestAndValidate,
updateOpenTestCaseIndex,
handleClickCancelPublish,
} from './ojForm';
import {
@ -79,6 +80,7 @@ export default {
validateOjTimeLimit,
validateOjCategory,
validateOpenOrNot,
handleClickCancelPublish,
addTestCase,
deleteTestCase,
testCaseInputChange,

@ -4,11 +4,16 @@
* @Github:
* @Date: 2019-11-20 16:35:46
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 19:54:56
* @LastEditTime: 2019-12-13 10:46:15
*/
import types from './actionTypes';
import CONST from '../../constants';
import { fetchPostOjForm, fetchGetOjById, publishTask } from '../../services/ojService';
import {
fetchPostOjForm,
fetchGetOjById,
publishTask,
cancelPublicTask
} from '../../services/ojService';
import { Base64 } from 'js-base64';
import { message, notification, Modal } from 'antd';
import { toStore } from 'educoder';
@ -80,6 +85,18 @@ const payloadInfo = (key, value, errMsg, validateInfo) => ({
}
});
// 接口调用成功后,跳转至列表页
function linkToDev (dispatch, props) {
toStore('oj_description', '');
dispatch({
type: types.IS_MY_SOURCE,
payload: true
});
setTimeout(() => {
props.history.push('/problems');
}, 1000);
}
// 表单提交验证
export const validateOjForm = (props, type) => {
return (dispatch, getState) => {
@ -229,59 +246,31 @@ export const validateOjForm = (props, type) => {
paramsObj['identifier'] = identifier;
}
// 接口调用成功后,跳转至列表页
function linkToDev () {
toStore('oj_description', '');
dispatch({
type: types.IS_MY_SOURCE,
payload: true
});
setTimeout(() => {
props.history.push('/problems');
}, 1000);
}
// 调用保存或更新
if (type === 'publish') {
// 提示发布信息
Modal.confirm({
title: '提示',
content: `
发布后即可应用到自己管理的课堂,
是否确定发布?`,
okText: '确定',
cancelText: '取消',
onOk () {
publishTask(identifier).then(res => {
if (res.data.status === 0) {
message.success('发布成功!');
linkToDev();
}
dispatch({
type: types.PUBLISH_LOADING_STATUS,
payload: false
});
}).catch(() => {
dispatch({
type: types.PUBLISH_LOADING_STATUS,
payload: false
});
});
},
onCancel () {
dispatch({
type: types.PUBLISH_LOADING_STATUS,
payload: false
});
publishTask(identifier).then(res => {
if (res.data.status === 0) {
message.success('发布成功!');
linkToDev(dispatch, props);
}
dispatch({
type: types.PUBLISH_LOADING_STATUS,
payload: false
});
}).catch(() => {
dispatch({
type: types.PUBLISH_LOADING_STATUS,
payload: false
});
});
} else {
// 调用更新
fetchPostOjForm(paramsObj).then(res => {
if (res.status === 200) { // 保存成功后,重新跳转至列表页
if (res.data.identifier) {
message.success('保存成功!');
linkToDev();
if (res.data.status === 0) {
message.success(paramsObj['submitType'] === 'update' ? '更新成功' : '保存成功');
linkToDev(dispatch, props);
}
dispatch({
type: types.SUBMIT_LOADING_STATUS,
@ -299,6 +288,29 @@ export const validateOjForm = (props, type) => {
}
}
};
// 撤销发布
export const handleClickCancelPublish = (props, identifier) => {
return (dispatch) => {
cancelPublicTask(identifier).then(res => {
dispatch({
type: types.PUBLISH_LOADING_STATUS,
payload: false
});
if (res.status = 200) {
const { data} = res;
if (data.status === 0) {
message.success('撤销发布成功!');
linkToDev(dispatch, props);
}
}
}).catch(() => {
dispatch({
type: types.PUBLISH_LOADING_STATUS,
payload: false
});
})
}
}
// 保存提交的代码
export const saveOjFormCode = (value) => {
return {

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 16:40:32
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-09 16:30:46
* @LastEditTime: 2019-12-13 11:54:35
*/
import { Base64 } from 'js-base64';
import types from '../actions/actionTypes';
@ -146,12 +146,16 @@ const ojFormReducer = (state = initialState, action) => {
const { position } = action.payload;
// 根据 position 去查找当前元素在数组中的位置
const index = state.testCases.findIndex((item) => item.position === position);
const tempTestCase = state.testCases || [];
const tempTestValicate = state.testCasesValidate || [];
if (index > -1) {
state.testCases.splice(index, 1); // 删除当前元素
state.testCasesValidate.splice(index, 1); // 删除测试用例对应的校验
tempTestCase.splice(index, 1); // 删除当前元素
tempTestValicate.splice(index, 1); // 删除测试用例对应的校验
}
return {
...state
...state,
testCases: [...tempTestCase],
testCasesValidate: [...tempTestValicate]
};
case types.SAVE_OJ_FORM_ID:
state.identifier = action.payload;

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-20 10:55:38
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 20:46:16
* @LastEditTime: 2019-12-13 10:09:12
*/
import axios from 'axios';
@ -95,6 +95,12 @@ export async function publishTask (identifier) {
return axios.post(url);
}
// 撤销发布
export async function cancelPublicTask (identifier) {
const url = `/problems/${identifier}/cancel_publish.json`;
return axios.post(url);
}
// 更新用户编辑代码
export async function fetchUpdateCode (identifier, params) {
const url = `/myproblems/${identifier}/update_code.json`;

Loading…
Cancel
Save