feat: 题目新增选项编辑
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
This commit is contained in:
parent
2137559c62
commit
6724e83beb
@ -123,6 +123,12 @@ const optionsHorizontal = computed(() => {
|
|||||||
return willSimpleOptionsHorizontal(normalizedOptions.value)
|
return willSimpleOptionsHorizontal(normalizedOptions.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 是否可在编辑弹窗中编辑选项(普通选择题)
|
||||||
|
const hasEditableOptions = computed(() => {
|
||||||
|
if (isWanXing.value || isYueDu.value) return false
|
||||||
|
return !!normalizedOptions.value?.length
|
||||||
|
})
|
||||||
|
|
||||||
// 显示答案那些
|
// 显示答案那些
|
||||||
const answerVisible = ref(false)
|
const answerVisible = ref(false)
|
||||||
const toggleAnswerVisible = () => {
|
const toggleAnswerVisible = () => {
|
||||||
@ -146,9 +152,31 @@ const stemUploading = ref(false)
|
|||||||
const stemEditorRef = ref<HTMLElement>()
|
const stemEditorRef = ref<HTMLElement>()
|
||||||
const answerEditorRef = ref<HTMLElement>()
|
const answerEditorRef = ref<HTMLElement>()
|
||||||
const explanationEditorRef = ref<HTMLElement>()
|
const explanationEditorRef = ref<HTMLElement>()
|
||||||
|
const optionEditorRefs = ref<HTMLElement[]>([])
|
||||||
|
const editOptions = ref<{ label: string; value: string }[]>([])
|
||||||
const stemUploadInputRef = ref<HTMLInputElement>()
|
const stemUploadInputRef = ref<HTMLInputElement>()
|
||||||
const stemSelectionRange = ref<null | Range>(null)
|
const stemSelectionRange = ref<null | Range>(null)
|
||||||
|
|
||||||
|
const setOptionEditorRef = (el: any, idx: number) => {
|
||||||
|
if (el) optionEditorRefs.value[idx] = el
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEditableOptionsFromQuestion() {
|
||||||
|
const opts = normalizedOptions.value
|
||||||
|
if (!opts?.length || isWanXing.value || isYueDu.value) return []
|
||||||
|
return opts.map((o: any) => ({
|
||||||
|
label: o.label ?? '',
|
||||||
|
value: o.value ?? '',
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildOptionHtmlFromEditors() {
|
||||||
|
return editOptions.value.map((opt, idx) => ({
|
||||||
|
index: opt.label,
|
||||||
|
html: optionEditorRefs.value[idx]?.innerHTML ?? opt.value ?? '',
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
const saveStemSelection = () => {
|
const saveStemSelection = () => {
|
||||||
const selection = window.getSelection()
|
const selection = window.getSelection()
|
||||||
if (!selection || selection.rangeCount === 0) return
|
if (!selection || selection.rangeCount === 0) return
|
||||||
@ -234,11 +262,17 @@ const handleEdit = () => {
|
|||||||
const q = props.question as any
|
const q = props.question as any
|
||||||
editDialogVisible.value = true
|
editDialogVisible.value = true
|
||||||
stemSelectionRange.value = null
|
stemSelectionRange.value = null
|
||||||
|
editOptions.value = getEditableOptionsFromQuestion()
|
||||||
|
optionEditorRefs.value = []
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (stemEditorRef.value) stemEditorRef.value.innerHTML = q.stem || ''
|
if (stemEditorRef.value) stemEditorRef.value.innerHTML = q.stem || ''
|
||||||
if (answerEditorRef.value) answerEditorRef.value.innerHTML = q.answer || ''
|
if (answerEditorRef.value) answerEditorRef.value.innerHTML = q.answer || ''
|
||||||
if (explanationEditorRef.value)
|
if (explanationEditorRef.value)
|
||||||
explanationEditorRef.value.innerHTML = q.explanation || ''
|
explanationEditorRef.value.innerHTML = q.explanation || ''
|
||||||
|
editOptions.value.forEach((opt, idx) => {
|
||||||
|
const el = optionEditorRefs.value[idx]
|
||||||
|
if (el) el.innerHTML = opt.value || ''
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,17 +283,27 @@ const handleEditSave = async () => {
|
|||||||
const stem = stemEditorRef.value?.innerHTML || ''
|
const stem = stemEditorRef.value?.innerHTML || ''
|
||||||
const answer = answerEditorRef.value?.innerHTML || ''
|
const answer = answerEditorRef.value?.innerHTML || ''
|
||||||
const explanation = explanationEditorRef.value?.innerHTML || ''
|
const explanation = explanationEditorRef.value?.innerHTML || ''
|
||||||
await saveOrUpdateXkwQuestionTitle({
|
const payload: Record<string, any> = {
|
||||||
id: q.id,
|
id: q.id,
|
||||||
stem,
|
stem,
|
||||||
stemHtml: stem,
|
stemHtml: stem,
|
||||||
answer,
|
answer,
|
||||||
answerHtml: answer,
|
answerHtml: answer,
|
||||||
explanation,
|
explanation,
|
||||||
})
|
}
|
||||||
|
if (hasEditableOptions.value && editOptions.value.length) {
|
||||||
|
const optionData = buildOptionHtmlFromEditors()
|
||||||
|
const optionHtml = JSON.stringify(optionData)
|
||||||
|
payload.optionHtml = optionHtml
|
||||||
|
}
|
||||||
|
await saveOrUpdateXkwQuestionTitle(payload)
|
||||||
q.stem = stem
|
q.stem = stem
|
||||||
q.answer = answer
|
q.answer = answer
|
||||||
q.explanation = explanation
|
q.explanation = explanation
|
||||||
|
if (payload.optionHtml) {
|
||||||
|
q.optionHtml = payload.optionHtml
|
||||||
|
q.optionList = JSON.parse(payload.optionHtml)
|
||||||
|
}
|
||||||
editDialogVisible.value = false
|
editDialogVisible.value = false
|
||||||
ElMessage.success('保存成功')
|
ElMessage.success('保存成功')
|
||||||
} finally {
|
} finally {
|
||||||
@ -504,6 +548,21 @@ const handleEditSave = async () => {
|
|||||||
@blur="saveStemSelection"
|
@blur="saveStemSelection"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="hasEditableOptions" class="edit-field">
|
||||||
|
<div class="edit-field-label">选项</div>
|
||||||
|
<div
|
||||||
|
v-for="(opt, idx) in editOptions"
|
||||||
|
:key="opt.label"
|
||||||
|
class="edit-option-item"
|
||||||
|
>
|
||||||
|
<span class="edit-option-label">{{ opt.label }}.</span>
|
||||||
|
<div
|
||||||
|
:ref="(el) => setOptionEditorRef(el, idx)"
|
||||||
|
class="edit-field-editor paper-question-item edit-option-editor"
|
||||||
|
contenteditable="true"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="edit-field">
|
<div class="edit-field">
|
||||||
<div class="edit-field-label">答案</div>
|
<div class="edit-field-label">答案</div>
|
||||||
<div
|
<div
|
||||||
@ -1143,6 +1202,25 @@ $padding: 16px;
|
|||||||
content: '请输入内容';
|
content: '请输入内容';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.edit-option-item {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.edit-option-label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
min-width: 24px;
|
||||||
|
padding-top: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-option-editor {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user