Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_item_bank
@ -1,7 +1,7 @@
|
|||||||
json.single_questions_count @single_questions_count
|
json.single_questions_count @basket_count&.fetch("SINGLE", 0)
|
||||||
json.multiple_questions_count @multiple_questions_count
|
json.multiple_questions_count @basket_count&.fetch("MULTIPLE", 0)
|
||||||
json.judgement_questions_count @judgement_questions_count
|
json.judgement_questions_count @basket_count&.fetch("JUDGMENT", 0)
|
||||||
json.completion_questions_count @completion_questions_count
|
json.completion_questions_count @basket_count&.fetch("COMPLETION", 0)
|
||||||
json.subjective_questions_count @subjective_questions_count
|
json.subjective_questions_count @basket_count&.fetch("SUBJECTIVE", 0)
|
||||||
json.practical_questions_count @practical_questions_count
|
json.practical_questions_count @basket_count&.fetch("PRACTICAL", 0)
|
||||||
json.program_questions_count @program_questions_count
|
json.program_questions_count @basket_count&.fetch("PROGRAM", 0)
|
@ -0,0 +1,17 @@
|
|||||||
|
class AddChoiceIndexToExerciseAnswers < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
add_column :exercise_answers, :choice_index, :integer, default: 1
|
||||||
|
|
||||||
|
multi_questions = ExerciseQuestion.where(question_type: 1)
|
||||||
|
multi_questions.includes(:exercise_choices, :exercise_answers).find_each do |question|
|
||||||
|
exercise_answers = question.exercise_answers
|
||||||
|
exercise_answers.find_each do |answer|
|
||||||
|
choice_index = question.exercise_choices.pluck(:id).index(answer.exercise_choice_id).to_i + 1
|
||||||
|
answer.update_column('choice_index', choice_index)
|
||||||
|
end
|
||||||
|
puts "multi_questions: #{question.id}"
|
||||||
|
end
|
||||||
|
|
||||||
|
ExerciseAnswer.joins(:exercise_question).where(exercise_questions: {question_type: 3}).update_all("choice_index = exercise_choice_id")
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,13 @@
|
|||||||
|
class AddChoiceIndexUniqIndexToExerciseAnswers < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
sql = %Q(delete from exercise_answers where (exercise_question_id, user_id, choice_index) in
|
||||||
|
(select * from (select exercise_question_id, user_id, choice_index from exercise_answers group by exercise_question_id, user_id, choice_index having count(*) > 1) a)
|
||||||
|
and id not in (select * from (select max(id) from exercise_answers group by exercise_question_id, user_id, choice_index having count(*) > 1 order by id) b))
|
||||||
|
ActiveRecord::Base.connection.execute sql
|
||||||
|
|
||||||
|
add_index :exercise_answers, [:exercise_question_id, :user_id, :choice_index], name: 'exercise_user_choice_index', unique: true
|
||||||
|
|
||||||
|
remove_index :exercise_answers, name: :exercise_choice_index
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 381 KiB After Width: | Height: | Size: 383 KiB |
After Width: | Height: | Size: 52 KiB |
@ -0,0 +1,367 @@
|
|||||||
|
.wx-code-area{
|
||||||
|
height: 100vh;
|
||||||
|
overflow: hidden;
|
||||||
|
.wx-code-flex{
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.wx-code-item{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.wx-code-test{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 150px;
|
||||||
|
background-color: #052645;
|
||||||
|
padding: 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-btn{
|
||||||
|
display: flex;
|
||||||
|
.icon-btn{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
color: #2EA4FF;
|
||||||
|
align-items: center;
|
||||||
|
.icon{
|
||||||
|
// font-size: 24px !important;
|
||||||
|
// transform: scale(2.4);
|
||||||
|
// line-height: 2;
|
||||||
|
font-size: 34px !important;
|
||||||
|
transform: scale(1.8);
|
||||||
|
position: relative;
|
||||||
|
// top: 10px;
|
||||||
|
}
|
||||||
|
// .icon-reset{
|
||||||
|
// transform: scale(2.4);
|
||||||
|
// }
|
||||||
|
// .icon:first-child{
|
||||||
|
// transform: scale((3));
|
||||||
|
// }
|
||||||
|
|
||||||
|
&:last-child{
|
||||||
|
margin-left: 60px;
|
||||||
|
}
|
||||||
|
.icon-txt{
|
||||||
|
// margin-top: 5px;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wx-pt-btn{
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
border-radius: 9999px;
|
||||||
|
padding: 0 50px;
|
||||||
|
line-height: 92px;
|
||||||
|
font-size: 38px;
|
||||||
|
color: #fff;
|
||||||
|
background:#2EA4FF;
|
||||||
|
letter-spacing: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wx-code-test-case{
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
transform: translateY(100%);
|
||||||
|
transition: transform, opacity .3s;
|
||||||
|
opacity: 0;
|
||||||
|
// border-top-left-radius: 16px;
|
||||||
|
// border-top-right-radius: 16px;
|
||||||
|
|
||||||
|
&::before{
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
content: '';
|
||||||
|
background: rgba(0,0,0,.6);
|
||||||
|
}
|
||||||
|
.text-case-list{
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
bottom: 0;
|
||||||
|
top: 150px;
|
||||||
|
background:rgba(1,14,31,1);
|
||||||
|
border-top-left-radius: 16px;
|
||||||
|
border-top-right-radius: 16px;
|
||||||
|
border:2px solid rgba(33,56,87,1);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 88px;
|
||||||
|
padding: 30px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-bottom: 2px solid #213857;
|
||||||
|
.header-title{
|
||||||
|
color:#637DA6;
|
||||||
|
// font-size: 24px;
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
.header-close{
|
||||||
|
// font-size: 42px;
|
||||||
|
font-size: 48px;
|
||||||
|
color: #2EA4FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wxcode-test-result{
|
||||||
|
// display: flex;
|
||||||
|
display: none;
|
||||||
|
height: 72px;
|
||||||
|
// background: gold;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 30px;
|
||||||
|
.success{
|
||||||
|
color: rgba(68,209,95,1);
|
||||||
|
}
|
||||||
|
.fail{
|
||||||
|
color: rgba(196, 79, 78, 1);
|
||||||
|
}
|
||||||
|
.icon{
|
||||||
|
font-size: 48px !important;
|
||||||
|
position: relative;
|
||||||
|
// top: -8px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.result-txt{
|
||||||
|
// font-size: 34px;
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
.result-txt-desc{
|
||||||
|
max-width: 500px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow:ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
display: flex;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.case-list{
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0px;
|
||||||
|
overflow: auto;
|
||||||
|
margin-top: 88px;
|
||||||
|
padding: 0 30px 30px;
|
||||||
|
// margin: 88px 30px 0;
|
||||||
|
.case-item{
|
||||||
|
position: relative;
|
||||||
|
margin-top: 30px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background:rgba(23,39,64,1);
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hasResult{
|
||||||
|
margin-top: 170px;
|
||||||
|
|
||||||
|
.case-item:first-child{
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.case-item-header{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
.case_item_success,
|
||||||
|
.case_item_fail{
|
||||||
|
font-size: 24px !important;
|
||||||
|
transform: scale(2);
|
||||||
|
}
|
||||||
|
.case_item_success{
|
||||||
|
color: rgba(68,209,95,1);
|
||||||
|
}
|
||||||
|
.case_item_fail{
|
||||||
|
color: rgba(196, 79, 78, 1);
|
||||||
|
}
|
||||||
|
.case-item-tips{
|
||||||
|
color: #C67676;
|
||||||
|
font-size: 38px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-header-desc{
|
||||||
|
font-size: 48px;
|
||||||
|
color: #405D8C;
|
||||||
|
line-height: 1.5;
|
||||||
|
// background: gold;
|
||||||
|
.icon{
|
||||||
|
position: relative;
|
||||||
|
top: -4px;
|
||||||
|
font-size: 42px !important;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.case-item-tips{
|
||||||
|
font-size: 42px;
|
||||||
|
}
|
||||||
|
.case-item-desc{
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 42px;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
&.active{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.desc-title{
|
||||||
|
color: #637DA6;
|
||||||
|
line-height: 2;
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
.text-area-style{
|
||||||
|
background:#010E1F !important;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 48px;
|
||||||
|
line-height: 1.5;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active{
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
// .item-header-desc{
|
||||||
|
// color: #fff;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.code-evaluate-loading,
|
||||||
|
.pass-dialog{
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
top: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
&::before{
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
content: '';
|
||||||
|
background: rgba(0,0,0,.5);
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.code-evaluate-loading{
|
||||||
|
// display: none;
|
||||||
|
.loading-flex{
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
.loading-icon{
|
||||||
|
font-size: 100px !important;
|
||||||
|
}
|
||||||
|
.loading-txt{
|
||||||
|
font-size: 42px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pass-dialog{
|
||||||
|
flex-direction: column;
|
||||||
|
.pass-box{
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 15px;
|
||||||
|
width: 490px;
|
||||||
|
height: 490px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.pass-img{
|
||||||
|
height: 200px;
|
||||||
|
background: url(../../images/wx-head.png) center center no-repeat;
|
||||||
|
// background: url(../../../public/images/wx-head.png) center center no-repeat;
|
||||||
|
}
|
||||||
|
.pass-ctx{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
// justify-content: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 290px;
|
||||||
|
padding: 40px 0;
|
||||||
|
.pass-title,
|
||||||
|
.pass-value,
|
||||||
|
.pass-btn .btn,
|
||||||
|
.pass-btn-all .btn{
|
||||||
|
font-size: 42px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.pass-value{
|
||||||
|
color: #888888;
|
||||||
|
.value_color{
|
||||||
|
color: rgb(234, 185, 35);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pass-btn,
|
||||||
|
.pass-btn-all{
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
// background: gold;
|
||||||
|
padding: 0 40px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.pass-btn-all{
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.btn{
|
||||||
|
outline: none;
|
||||||
|
border-radius: 999px;
|
||||||
|
padding: 0 30px;
|
||||||
|
height: 70px;
|
||||||
|
&.btn-first{
|
||||||
|
border: 1px solid #2EA4FF;
|
||||||
|
color: #2EA4FF;
|
||||||
|
}
|
||||||
|
&.btn-second{
|
||||||
|
background-color: #2EA4FF;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pass-title{
|
||||||
|
color: #2EA4FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.icon_close{
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
color: #555;
|
||||||
|
font-size: 100px!important;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* @Description:
|
||||||
|
* @Author: tangjiang
|
||||||
|
* @Github:
|
||||||
|
* @Date: 2020-01-15 15:37:44
|
||||||
|
* @LastEditors : tangjiang
|
||||||
|
* @LastEditTime : 2020-01-18 09:46:04
|
||||||
|
*/
|
||||||
|
import types from "../actions/actionTypes";
|
||||||
|
const initialState = {
|
||||||
|
wxCode: '',
|
||||||
|
userCode: '',
|
||||||
|
testCase: [],
|
||||||
|
game_id: '',
|
||||||
|
myIdentifier: '',
|
||||||
|
exec_time: 0,
|
||||||
|
last_compile_output: '',
|
||||||
|
test_sets_count: 0,
|
||||||
|
sets_error_count: 0,
|
||||||
|
path: '',
|
||||||
|
isShow: false,
|
||||||
|
showLoading: false,
|
||||||
|
showDialog: false,
|
||||||
|
gold: 0,
|
||||||
|
experience: 0,
|
||||||
|
next_game: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
const wxcodeReducer = (state = initialState, action) => {
|
||||||
|
const { payload, type } = action;
|
||||||
|
switch (type) {
|
||||||
|
case types.GET_WXCODE_BY_IDENTIFIER:
|
||||||
|
console.log('=====>>>>>', payload);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
wxCode: payload,
|
||||||
|
userCode: payload
|
||||||
|
}
|
||||||
|
case types.GET_WXCODE_TEST_CASE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
testCase: payload.test_sets,
|
||||||
|
game_id: payload.game_id,
|
||||||
|
myIdentifier: payload.myIdentifier,
|
||||||
|
exec_time: payload.exec_time,
|
||||||
|
path: payload.path,
|
||||||
|
last_compile_output: payload.last_compile_output,
|
||||||
|
test_sets_count: payload.test_sets_count,
|
||||||
|
sets_error_count: payload.sets_error_count
|
||||||
|
}
|
||||||
|
case types.UPDATE_WXCODE_FOR_EDITOR:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
userCode: payload
|
||||||
|
}
|
||||||
|
case types.IS_SHOW_WXCODE_TEST_CASES:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isShow: payload
|
||||||
|
}
|
||||||
|
case types.SHOW_WX_CODE_LOADING:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
showLoading: payload
|
||||||
|
}
|
||||||
|
case types.SHOW_WX_CODE_DIALOG:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
showDialog: payload
|
||||||
|
}
|
||||||
|
case types.SET_GOLD_AND_EXPERIENCE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
gold: payload.gold,
|
||||||
|
experience: payload.experience,
|
||||||
|
next_game: payload.next_game
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return {
|
||||||
|
...state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default wxcodeReducer;
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* @Description:
|
||||||
|
* @Author: tangjiang
|
||||||
|
* @Github:
|
||||||
|
* @Date: 2020-01-15 15:44:36
|
||||||
|
* @LastEditors : tangjiang
|
||||||
|
* @LastEditTime : 2020-01-17 20:39:13
|
||||||
|
*/
|
||||||
|
import axios from 'axios';
|
||||||
|
import cookie from 'react-cookies'
|
||||||
|
// axios.defaults.withCredentials = true;
|
||||||
|
|
||||||
|
|
||||||
|
const setCookier = () => {
|
||||||
|
const _params = window.location.search;
|
||||||
|
if (_params) {
|
||||||
|
let _search = _params.split('?')[1];
|
||||||
|
_search.split('&').forEach(item => {
|
||||||
|
// console.log(item);
|
||||||
|
const _arr = item.split('=');
|
||||||
|
cookie.remove(_arr[0], {
|
||||||
|
path: '/',
|
||||||
|
domain: '.educoder.net'
|
||||||
|
});
|
||||||
|
cookie.save(_arr[0], _arr[1], { domain: '.educoder.net', path: '/'});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取代码块
|
||||||
|
export async function fetchWxCode (identifier, params) {
|
||||||
|
setCookier();
|
||||||
|
const url = `/tasks/${identifier}/rep_content.json`;
|
||||||
|
params = Object.assign({}, params, {withCredentials: true});
|
||||||
|
return axios.get(url, {params});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取测试值
|
||||||
|
export async function fetchWxCodeTextCase (identifier) {
|
||||||
|
setCookier();
|
||||||
|
const url = `/tasks/${identifier}.json`;
|
||||||
|
const params = Object.assign({}, {withCredentials: true});
|
||||||
|
return axios.get(url, {params});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新代码块内容
|
||||||
|
export async function fetchUpdateWxCode (identifier, params) {
|
||||||
|
setCookier();
|
||||||
|
// /myshixuns/8etu3pilsa/update_file.json
|
||||||
|
const url = `/myshixuns/${identifier}/update_file.json`;
|
||||||
|
params = Object.assign({}, params, {withCredentials: true});
|
||||||
|
return axios.post(url, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 恢复初始化
|
||||||
|
export async function fetchRestoreWxCode (identifier, params) {
|
||||||
|
setCookier();
|
||||||
|
const url = `/tasks/${identifier}/reset_original_code.json`;
|
||||||
|
params = Object.assign({}, params, {withCredentials: true});
|
||||||
|
return axios.get(url, {params});
|
||||||
|
}
|
||||||
|
// 评测
|
||||||
|
export async function fetchWxCodeGameBuild (identifier, params) {
|
||||||
|
setCookier();
|
||||||
|
const url = `/tasks/${identifier}/game_build.json`;
|
||||||
|
params = Object.assign({}, params, {withCredentials: true});
|
||||||
|
return axios.get(url, {params});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchWxCodeGameStatus (identifier, params) {
|
||||||
|
setCookier();
|
||||||
|
const url = `/tasks/${identifier}/game_status.json`;
|
||||||
|
params = Object.assign({}, params, {withCredentials: true});
|
||||||
|
return axios.get(url, {params});
|
||||||
|
}
|
Before Width: | Height: | Size: 381 KiB After Width: | Height: | Size: 383 KiB |