于宏哲PHP 10 months ago
parent
commit
d29abf4f5e
  1. 3
      admin/src/app/api/exam_questions.ts
  2. 92
      admin/src/app/views/exam_papers/components/exam-papers-edit.vue
  3. 103
      admin/src/app/views/exam_questions/components/exam-questions-edit.vue
  4. 8
      niucloud/app/adminapi/controller/exam_papers/ExamPapers.php
  5. 17
      niucloud/app/adminapi/controller/exam_questions/ExamQuestions.php
  6. 5
      niucloud/app/adminapi/route/exam_questions.php
  7. 4
      niucloud/app/service/admin/exam_papers/ExamPapersService.php
  8. 29
      niucloud/app/service/admin/exam_questions/ExamQuestionsService.php

3
admin/src/app/api/exam_questions.ts

@ -49,6 +49,9 @@ export function deleteExamQuestions(id: number) {
return request.delete(`exam_questions/exam_questions/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
export function randomQuestionsList(params: Record<string, any>) {
return request.post(`exam_questions/random_questions_list`, params, { showErrorMessage: true, showSuccessMessage: true })
}
// USER_CODE_END -- exam_questions

92
admin/src/app/views/exam_papers/components/exam-papers-edit.vue

@ -9,7 +9,7 @@
</el-form-item>
<el-form-item :label="t('selectionMode')" prop="selection_mode">
<el-form-item label="题目模式" prop="selection_mode">
<el-select class="input-width" v-model="formData.selection_mode" clearable
:placeholder="t('selectionModePlaceholder')">
<el-option label="请选择" value=""></el-option>
@ -18,9 +18,40 @@
</el-select>
</el-form-item>
<!-- <el-form-item :label="t('questionsIds')" >
<el-input v-model="formData.questions_ids" clearable :placeholder="t('questionsIdsPlaceholder')" class="input-width" />
</el-form-item> -->
<el-form-item label="单选题" v-if="formData.selection_mode === 'random'">
<el-row :gutter="20" class="random-count-row">
<el-col :span="8">
<el-form-item >
<el-input-number v-model="formData.single_choice_count" placeholder="数量" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="多选题" label-width="60px">
<el-input-number v-model="formData.multiple_choice_count" placeholder="数量" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="判断题" label-width="60px">
<el-input-number v-model="formData.true_false_count" placeholder="数量" />
</el-form-item>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addOption" v-if="formData.selection_mode === 'random'">
<view v-if="formData.questions_ids == ''">随机题库</view>
<view v-if="formData.questions_ids !== ''">重新随机题库</view>
</el-button>
</el-form-item>
<el-form-item :label="t('questionsIds')" v-if="formData.selection_mode == 'manual'">
<div class="mt-[10px]">
@ -53,7 +84,6 @@
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
@ -64,9 +94,15 @@
</div>
</el-form-item>
<el-form-item label="每题分数">
<el-input-number v-model="formData.every_score" class="input-width" />
</el-form-item>
<el-form-item :label="t('totalScore')" prop="total_score">
<el-input-number v-model="formData.total_score" clearable :placeholder="t('totalScorePlaceholder')"
<el-input-number disabled v-model="formData.total_score" clearable :placeholder="t('totalScorePlaceholder')"
class="input-width" :min="0" max="100" />
</el-form-item>
@ -100,7 +136,7 @@
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { addExamPapers, editExamPapers, getExamPapersInfo } from '@/app/api/exam_papers'
import { getExamQuestionsList } from '@/app/api/exam_questions'
import { getExamQuestionsList,randomQuestionsList } from '@/app/api/exam_questions'
let showDialog = ref(false)
const loading = ref(false)
@ -115,8 +151,26 @@
questions_ids: '',
total_score: '',
passing_score: '',
single_choice_count:0,
multiple_choice_count:0,
true_false_count:0,
every_score:0
}
const addOption = () => {
randomQuestionsList({
single_choice_count: formData.single_choice_count,
multiple_choice_count: formData.multiple_choice_count,
true_false_count: formData.true_false_count
}).then(res => {
formData.questions_ids = res.data.questions_ids;
console.log(res.data.questions_ids);
}).catch(() => {
})
}
//
@ -164,6 +218,9 @@
const handleSelectionChange = (val) => {
selectedQuestions.value = val
const ids = selectedQuestions.value.map(item => item.id).join(',')
formData.questions_ids = ids
}
@ -171,7 +228,18 @@
const formData : Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
watch(
() => [formData.questions_ids, formData.every_score],
([newIds, newScore]) => {
const count = newIds ? newIds.split(',').filter(id => id.trim() !== '').length : 0;
const score = Number(newScore) || 0;
formData.total_score = count * score;
},
{ immediate: true }
);
//
const formRules = computed(() => {
return {
@ -196,10 +264,10 @@
if (valid) {
loading.value = true
if (formData.selection_mode == 'manual') {
const ids = selectedQuestions.value.map(item => item.id).join(',')
formData.questions_ids = ids
}
// if (formData.selection_mode == 'manual') {
// const ids = selectedQuestions.value.map(item => item.id).join(',')
// formData.questions_ids = ids
// }
let data = formData

103
admin/src/app/views/exam_questions/components/exam-questions-edit.vue

@ -9,7 +9,7 @@
<el-form-item :label="t('questionType')" prop="question_type">
<el-select class="input-width" v-model="formData.question_type" clearable
:placeholder="t('questionTypePlaceholder')">
:placeholder="t('questionTypePlaceholder')" @change="typeChenge(index)">
<el-option label="请选择" value=""></el-option>
<el-option v-for="(item, index) in question_typeList" :key="index" :label="item.name"
:value="item.value" />
@ -34,15 +34,17 @@
<upload-image v-model="formData.question_content" />
</el-form-item>
<!-- <el-form-item :label="t('optionJson')" prop="option_json">
<el-input v-model="formData.option_json" clearable :placeholder="t('optionJsonPlaceholder')" class="input-width" />
</el-form-item> -->
<el-form-item :label="t('optionJson')">
<div v-for="(option, index) in formData.option_json" :key="index" class="option-item">
<el-card class="box-card" shadow="never">
<el-form-item label="类型" label-width="60">
<el-form-item label="编号" label-width="60" >
<el-input v-model="option.option" placeholder="请输入编号" disabled/>
</el-form-item>
<el-form-item label="类型" label-width="60" style="margin-top:5px;">
<el-select v-model="option.option_content_type" placeholder="请选择类型">
<el-option label="文本" value="text" />
<el-option label="图片" value="image" />
@ -57,26 +59,39 @@
<upload-file v-model="option.option_content" />
</template>
</el-form-item>
<el-form-item label="答案" label-width="60">
<el-switch v-model="option.correct_answer"
:disabled="formData.question_type === 'single_choice' && option.correct_answer"
@change="handleCorrectAnswerChange(index)" />
</el-form-item>
<el-form-item label="操作" label-width="60">
<el-button @click="removeOption(index)" type="danger" size="small" plain>删除</el-button>
<el-radio-group v-model="option.correct_answer" v-if="formData.question_type == 'single_choice'" @change="radioChange(index)" >
<el-radio :label="true">正确答案</el-radio>
</el-radio-group>
<el-checkbox
v-model="option.correct_answer"
label="正确答案"
:value="true"
@change="handleCorrectAnswerChange(index)"
v-if="formData.question_type == 'multiple_choice' || formData.question_type == 'true_false'"
/>
<el-button @click="removeOption(index)" type="danger" size="small" plain style="margin-left:5px;">删除</el-button>
</el-form-item>
</el-card>
</div>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addOption">添加选项</el-button>
</el-form-item>
<el-form-item label="正确答案" prop="correct_answer">
<el-input v-model="formData.correct_answer" clearable placeholder="请输入正确答案" class="input-width" />
</el-form-item>
</el-form>
@ -111,29 +126,69 @@
question_type: '',
question_content_type: '',
question_content: '',
option_json: []
option_json: [],
correct_answer:''
}
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const addOption = () => {
const index = formData.option_json.length;
formData.option_json.push({
option_content_type: 'text',
option_content: '',
correct_answer: false
correct_answer: false,
option:alphabet[index] || ''
})
}
const removeOption = (index) => {
formData.option_json.splice(index, 1)
formData.option_json.forEach((opt, i) => {
opt.option = alphabet[i];
})
handleCorrectAnswerChange();
}
const typeChenge = () => {
formData.option_json.forEach((opt, i) => {
opt.correct_answer = false;
})
formData.correct_answer = '';
}
const handleCorrectAnswerChange = (changedIndex) => {
if (formData.question_type === 'single_choice') {
formData.options.forEach((opt, i) => {
if (i !== changedIndex) opt.correct_answer = false
})
}
const correct_answer = [];
formData.option_json.forEach((opt, i) => {
if (opt.correct_answer){
correct_answer.push(opt.option);
}
})
formData.correct_answer = correct_answer.join(",");
}
const radioChange = (changedIndex) => {
formData.option_json.forEach((opt, i) => {
opt.correct_answer = false;
})
formData.option_json[changedIndex].correct_answer = true;
formData.correct_answer = formData.option_json[changedIndex].option;
}
const formData : Record<string, any> = reactive({ ...initialFormData })

8
niucloud/app/adminapi/controller/exam_papers/ExamPapers.php

@ -54,6 +54,10 @@ class ExamPapers extends BaseAdminController
["questions_ids",""],
["total_score",0.00],
["passing_score",0.00],
["single_choice_count",0],
["multiple_choice_count",0],
["true_false_count",0],
["every_score",0]
]);
$this->validate($data, 'app\validate\exam_papers\ExamPapers.add');
@ -73,6 +77,10 @@ class ExamPapers extends BaseAdminController
["questions_ids",""],
["total_score",0.00],
["passing_score",0.00],
["single_choice_count",0],
["multiple_choice_count",0],
["true_false_count",0],
["every_score",0]
]);
$this->validate($data, 'app\validate\exam_papers\ExamPapers.edit');

17
niucloud/app/adminapi/controller/exam_questions/ExamQuestions.php

@ -54,7 +54,8 @@ class ExamQuestions extends BaseAdminController
["question_type",""],
["question_content_type",""],
["question_content",""],
["option_json",[]]
["option_json",[]],
["correct_answer",""]
]);
$this->validate($data, 'app\validate\exam_questions\ExamQuestions.add');
@ -73,7 +74,8 @@ class ExamQuestions extends BaseAdminController
["question_type",""],
["question_content_type",""],
["question_content",""],
["option_json",[]]
["option_json",[]],
["correct_answer",""]
]);
$this->validate($data, 'app\validate\exam_questions\ExamQuestions.edit');
@ -92,4 +94,15 @@ class ExamQuestions extends BaseAdminController
}
public function random_questions_list(){
$data = $this->request->params([
["single_choice_count",0],
["multiple_choice_count",0],
["true_false_count",0]
]);
return (new ExamQuestionsService())->random_questions_list($data);
}
}

5
niucloud/app/adminapi/route/exam_questions.php

@ -29,7 +29,10 @@ Route::group('exam_questions', function () {
Route::put('exam_questions/:id', 'exam_questions.ExamQuestions/edit');
//删除试题
Route::delete('exam_questions/:id', 'exam_questions.ExamQuestions/del');
Route::post('random_questions_list', 'exam_questions.ExamQuestions/random_questions_list');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,

4
niucloud/app/service/admin/exam_papers/ExamPapersService.php

@ -36,7 +36,7 @@ class ExamPapersService extends BaseAdminService
*/
public function getPage(array $where = [])
{
$field = 'id,title,selection_mode,questions_ids,total_score,passing_score,created_at,updated_at';
$field = 'id,title,selection_mode,questions_ids,single_choice_count,multiple_choice_count,true_false_count,total_score,every_score,passing_score,created_at,updated_at';
$order = 'id desc';
$search_model = $this->model->withSearch(["selection_mode","created_at"], $where)->field($field)->order($order);
@ -51,7 +51,7 @@ class ExamPapersService extends BaseAdminService
*/
public function getInfo(int $id)
{
$field = 'id,title,selection_mode,questions_ids,total_score,passing_score,created_at,updated_at';
$field = 'id,title,selection_mode,questions_ids,single_choice_count,multiple_choice_count,true_false_count,every_score,total_score,passing_score,created_at,updated_at';
$info = $this->model->field($field)->where([['id', "=", $id]])->findOrEmpty()->toArray();
return $info;

29
niucloud/app/service/admin/exam_questions/ExamQuestionsService.php

@ -36,7 +36,7 @@ class ExamQuestionsService extends BaseAdminService
*/
public function getPage(array $where = [])
{
$field = 'id,title,question_type,question_content_type,question_content,option_json,created_at,updated_at';
$field = 'id,title,question_type,question_content_type,correct_answer,question_content,option_json,created_at,updated_at';
$order = 'id desc';
$search_model = $this->model->withSearch(["title","question_type","created_at"], $where)->field($field)->order($order);
@ -51,7 +51,7 @@ class ExamQuestionsService extends BaseAdminService
*/
public function getInfo(int $id)
{
$field = 'id,title,question_type,question_content_type,question_content,option_json,created_at,updated_at';
$field = 'id,title,question_type,question_content_type,correct_answer,question_content,option_json,created_at,updated_at';
$info = $this->model->field($field)->where([['id', "=", $id]])->findOrEmpty()->toArray();
return $info;
@ -95,5 +95,30 @@ class ExamQuestionsService extends BaseAdminService
}
public function random_questions_list(array $data){
$singleChoiceIds = $data['single_choice_count'] > 0 ? $this->model
->where([['question_type', '=', 'single_choice']])
->orderRaw('RAND()')
->limit($data['single_choice_count'])
->column("id") : [];
$multipleChoiceIds = $data['multiple_choice_count'] > 0 ? $this->model
->where([['question_type', '=', 'multiple_choice']])
->orderRaw('RAND()')
->limit($data['multiple_choice_count'])
->column("id") : [];
$trueFalseIds = $data['true_false_count'] > 0 ? $this->model
->where([['question_type', '=', 'true_false']])
->orderRaw('RAND()')
->limit($data['true_false_count'])
->column("id") : [];
$questions_ids = array_merge($singleChoiceIds, $multipleChoiceIds, $trueFalseIds);
return success("随机成功", ['questions_ids' => implode(',', $questions_ids)]);
}
}

Loading…
Cancel
Save