Fix: Исправления для вопросов

 Ответы с картинками без текста теперь сохраняются
 TinyMCE инициализируется после DOMContentLoaded
 Валидация: хотя бы текст ИЛИ картинка в ответе
 Обновлены store и update методы

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
mirivlad 2026-03-27 10:41:14 +08:00
parent 1c94812f7d
commit ffcdd86712
2 changed files with 59 additions and 29 deletions

View File

@ -53,6 +53,20 @@ class QuestionController extends Controller
'ordering_items' => 'nullable|array',
]);
// Проверка что есть хотя бы текст или картинка в ответах
if ($validated['type'] === 'multiple_choice' && !empty($validated['answers'])) {
$hasValidAnswer = false;
foreach ($validated['answers'] as $answer) {
if (!empty($answer['text']) || !empty($answer['image'])) {
$hasValidAnswer = true;
break;
}
}
if (!$hasValidAnswer) {
return back()->withErrors(['answers' => 'Добавьте хотя бы один ответ (текст или картинку)'])->withInput();
}
}
DB::transaction(function () use ($test, $validated) {
$question = $test->questions()->create([
'type' => $validated['type'],
@ -66,7 +80,7 @@ class QuestionController extends Controller
// Ответы для multiple_choice
if ($validated['type'] === 'multiple_choice' && !empty($validated['answers'])) {
foreach ($validated['answers'] as $answer) {
if (!empty($answer['text'])) {
if (!empty($answer['text']) || !empty($answer['image'])) {
$imagePath = null;
if (!empty($answer['image'])) {
$imagePath = $answer['image']->store('questions/answers', 'public');
@ -145,6 +159,20 @@ class QuestionController extends Controller
'ordering_items' => 'nullable|array',
]);
// Проверка что есть хотя бы текст или картинка в ответах
if ($validated['type'] === 'multiple_choice' && !empty($validated['answers'])) {
$hasValidAnswer = false;
foreach ($validated['answers'] as $answer) {
if (!empty($answer['text']) || !empty($answer['image'])) {
$hasValidAnswer = true;
break;
}
}
if (!$hasValidAnswer) {
return back()->withErrors(['answers' => 'Добавьте хотя бы один ответ (текст или картинку)'])->withInput();
}
}
DB::transaction(function () use ($question, $validated) {
$question->update([
'type' => $validated['type'],
@ -159,7 +187,7 @@ class QuestionController extends Controller
if ($validated['type'] === 'multiple_choice' && !empty($validated['answers'])) {
$question->answers()->delete();
foreach ($validated['answers'] as $answer) {
if (!empty($answer['text'])) {
if (!empty($answer['text']) || !empty($answer['image'])) {
$imagePath = null;
if (!empty($answer['image'])) {
$imagePath = $answer['image']->store('questions/answers', 'public');

View File

@ -94,34 +94,36 @@
<!-- TinyMCE -->
<script src="https://cdn.tiny.mce.com/1/tinymce/7/tinymce.min.js" referrerpolicy="origin"></script>
<script>
// Инициализация TinyMCE
tinymce.init({
selector: '#questionText, #questionExplanation',
height: 300,
plugins: 'image link table lists code',
toolbar: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright | bullist numlist | image link | code',
image_title: true,
automatic_uploads: true,
file_picker_types: 'image',
file_picker_callback: function(cb, value, meta) {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.addEventListener('change', function(e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.addEventListener('load', function() {
const id = 'blobid' + (new Date()).getTime();
const blobCache = tinymce.activeEditor.editorUpload.blobCache;
const base64 = reader.result.split(',')[1];
const blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
cb(blobInfo.blobUri(), { title: file.name });
// Инициализация TinyMCE после загрузки DOM
document.addEventListener('DOMContentLoaded', function() {
tinymce.init({
selector: '#questionText, #questionExplanation',
height: 300,
plugins: 'image link table lists code',
toolbar: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright | bullist numlist | image link | code',
image_title: true,
automatic_uploads: true,
file_picker_types: 'image',
file_picker_callback: function(cb, value, meta) {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.addEventListener('change', function(e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.addEventListener('load', function() {
const id = 'blobid' + (new Date()).getTime();
const blobCache = tinymce.activeEditor.editorUpload.blobCache;
const base64 = reader.result.split(',')[1];
const blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
cb(blobInfo.blobUri(), { title: file.name });
});
reader.readAsDataURL(file);
});
reader.readAsDataURL(file);
});
input.click();
}
input.click();
}
});
});
function updateQuestionType() {