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

This commit is contained in:
阿梦 2026-05-19 19:54:48 +09:00
parent 2137559c62
commit 6724e83beb

View File

@ -123,6 +123,12 @@ const optionsHorizontal = computed(() => {
return willSimpleOptionsHorizontal(normalizedOptions.value)
})
//
const hasEditableOptions = computed(() => {
if (isWanXing.value || isYueDu.value) return false
return !!normalizedOptions.value?.length
})
//
const answerVisible = ref(false)
const toggleAnswerVisible = () => {
@ -146,9 +152,31 @@ const stemUploading = ref(false)
const stemEditorRef = ref<HTMLElement>()
const answerEditorRef = ref<HTMLElement>()
const explanationEditorRef = ref<HTMLElement>()
const optionEditorRefs = ref<HTMLElement[]>([])
const editOptions = ref<{ label: string; value: string }[]>([])
const stemUploadInputRef = ref<HTMLInputElement>()
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 selection = window.getSelection()
if (!selection || selection.rangeCount === 0) return
@ -234,11 +262,17 @@ const handleEdit = () => {
const q = props.question as any
editDialogVisible.value = true
stemSelectionRange.value = null
editOptions.value = getEditableOptionsFromQuestion()
optionEditorRefs.value = []
nextTick(() => {
if (stemEditorRef.value) stemEditorRef.value.innerHTML = q.stem || ''
if (answerEditorRef.value) answerEditorRef.value.innerHTML = q.answer || ''
if (explanationEditorRef.value)
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 answer = answerEditorRef.value?.innerHTML || ''
const explanation = explanationEditorRef.value?.innerHTML || ''
await saveOrUpdateXkwQuestionTitle({
const payload: Record<string, any> = {
id: q.id,
stem,
stemHtml: stem,
answer,
answerHtml: answer,
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.answer = answer
q.explanation = explanation
if (payload.optionHtml) {
q.optionHtml = payload.optionHtml
q.optionList = JSON.parse(payload.optionHtml)
}
editDialogVisible.value = false
ElMessage.success('保存成功')
} finally {
@ -504,6 +548,21 @@ const handleEditSave = async () => {
@blur="saveStemSelection"
></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-label">答案</div>
<div
@ -1143,6 +1202,25 @@ $padding: 16px;
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>