|
|
@@ -0,0 +1,279 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <a-spin :spinning="formLoading" tip="加载中...">
|
|
|
+ <a-form :model="form" ref="formRef" label-width="100px" :rules="rules">
|
|
|
+ <a-form-item label="年级:" prop="gradeLevel" required>
|
|
|
+ <a-select v-model:value="form.gradeLevel" placeholder="年级" :options="gradeLevelOptions" clearable />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="学科:" prop="subjectId" required>
|
|
|
+ <a-select v-model:value="form.subjectId" placeholder="学科" :options="susbjectOptions" />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="题干:" prop="title" required>
|
|
|
+ <a-input v-model="form.title" @focus="inputClick(form,'title')" />
|
|
|
+ <xn-editor v-model:value="form.title" :height="150"/>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="选项:" required>
|
|
|
+ <a-form-item :key="item.prefix" v-for="(item, index) in form.items" label-width="50px" class="question-item-label">
|
|
|
+ <template #label>
|
|
|
+ {{ item.prefix }}
|
|
|
+ </template>
|
|
|
+ <a-input v-model:value="item.prefix" style="width:50px;" />
|
|
|
+ <a-button type="primary" danger class="question-item-remove" @click="questionItemRemove(index)">删除</a-button>
|
|
|
+ <xn-editor v-model:value="item.content" :height="100"/>
|
|
|
+ </a-form-item>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="解析:" prop="analyze" required>
|
|
|
+ <xn-editor v-model:value="form.analyze" :height="150"/>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="分数:" prop="score" required>
|
|
|
+ <a-input-number v-model:value="form.score" :precision="1" :step="1" :max="100" />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="难度:" required>
|
|
|
+ <a-rate v-model:value="form.difficult" class="question-item-rate" />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="正确答案:" prop="correct" required>
|
|
|
+ <a-radio-group v-model:value="form.correct">
|
|
|
+ <a-radio v-for="item in form.items" :key="item.prefix" :value="item.prefix">{{ item.prefix }}</a-radio>
|
|
|
+ </a-radio-group>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item>
|
|
|
+ <a-button type="primary" @click="submitForm" style="margin-right: 10px;">提交</a-button>
|
|
|
+ <a-button @click="resetForm" style="margin-right: 10px;">重置</a-button>
|
|
|
+ <a-button type="success" @click="questionItemAdd" style="margin-right: 10px;">添加选项</a-button>
|
|
|
+ <a-button type="success" @click="showQuestion">预览</a-button>
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
+ </a-spin>
|
|
|
+
|
|
|
+ <a-modal
|
|
|
+ v-model:visible="richEditor.dialogVisible"
|
|
|
+ :footer="null"
|
|
|
+ :body-style="{ padding: '0' }"
|
|
|
+ :width="800"
|
|
|
+ centered
|
|
|
+ destroy-on-close
|
|
|
+ >
|
|
|
+ <Ueditor @ready="editorReady"/>
|
|
|
+ <a-button type="primary" @click="editorConfirm">确 定</a-button>
|
|
|
+ <a-button @click="richEditor.dialogVisible = false">取 消</a-button>
|
|
|
+ </a-modal>
|
|
|
+
|
|
|
+ <a-modal
|
|
|
+ v-model:visible="questionShow.dialog"
|
|
|
+ :footer="null"
|
|
|
+ :body-style="{ padding: '0' }"
|
|
|
+ :width="800"
|
|
|
+ centered
|
|
|
+ destroy-on-close
|
|
|
+ >
|
|
|
+ <QuestionShow :qType="questionShow.qType" :question="questionShow.question" :qLoading="questionShow.loading" />
|
|
|
+ </a-modal>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, reactive, onMounted } from 'vue'
|
|
|
+import { useRoute, useRouter } from 'vue-router'
|
|
|
+import questionApi from '@/api/question/tQuestionApi'
|
|
|
+import QuestionShow from '@/views/exm/question/components/Show.vue'
|
|
|
+import tool from "@/utils/tool"
|
|
|
+import XnEditor from '@/components/Editor/index.vue'
|
|
|
+import Ueditor from '@/components/Ueditor/index.vue'
|
|
|
+
|
|
|
+
|
|
|
+const route = useRoute()
|
|
|
+const router = useRouter()
|
|
|
+
|
|
|
+const formLoading = ref(false)
|
|
|
+// 表单引用
|
|
|
+const formRef = ref()
|
|
|
+
|
|
|
+// 数据初始化
|
|
|
+const form = ref({
|
|
|
+ id: null,
|
|
|
+ questionType: 1,
|
|
|
+ gradeLevel: null,
|
|
|
+ subjectId: null,
|
|
|
+ title: '',
|
|
|
+ items: [
|
|
|
+ { prefix: 'A', content: '' },
|
|
|
+ { prefix: 'B', content: '' },
|
|
|
+ { prefix: 'C', content: '' },
|
|
|
+ { prefix: 'D', content: '' }
|
|
|
+ ],
|
|
|
+ analyze: '',
|
|
|
+ correct: '',
|
|
|
+ score: '',
|
|
|
+ difficult: 0
|
|
|
+})
|
|
|
+
|
|
|
+const richEditor = reactive({
|
|
|
+ dialogVisible: false,
|
|
|
+ object: null,
|
|
|
+ parameterName: '',
|
|
|
+ instance: null
|
|
|
+})
|
|
|
+
|
|
|
+const questionShow = reactive({
|
|
|
+ qType: 0,
|
|
|
+ dialog: false,
|
|
|
+ question: null,
|
|
|
+ loading: false
|
|
|
+})
|
|
|
+
|
|
|
+const gradeLevelOptions = tool.dictList('SEMESTER')
|
|
|
+const susbjectOptions = tool.dictList('SUBJECT')
|
|
|
+const subjectFilter = ref(null)
|
|
|
+
|
|
|
+// 校验规则
|
|
|
+const rules = {
|
|
|
+ gradeLevel: [{ required: true, message: '请选择年级', trigger: 'change' }],
|
|
|
+ subjectId: [{ required: true, message: '请选择学科', trigger: 'change' }],
|
|
|
+ title: [{ required: true, message: '请输入题干', trigger: 'blur' }],
|
|
|
+ analyze: [{ required: true, message: '请输入解析', trigger: 'blur' }],
|
|
|
+ score: [{ required: true, message: '请输入分数', trigger: 'blur' }],
|
|
|
+ correct: [{ required: true, message: '请选择正确答案', trigger: 'change' }]
|
|
|
+}
|
|
|
+
|
|
|
+// 生命周期:组件挂载时处理路由参数
|
|
|
+onMounted(() => {
|
|
|
+ const id = route.query.id
|
|
|
+ if (id && parseInt(id) !== 0) {
|
|
|
+ formRef.value?.resetFields()
|
|
|
+ questionApi.select(id).then(re => {
|
|
|
+ Object.assign(form, re.response)
|
|
|
+ })
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 方法定义
|
|
|
+
|
|
|
+function editorReady(instance) {
|
|
|
+ richEditor.instance = instance
|
|
|
+ let currentContent = richEditor.object[richEditor.parameterName]
|
|
|
+ richEditor.instance.setContent(currentContent)
|
|
|
+ richEditor.instance.focus(true)
|
|
|
+}
|
|
|
+
|
|
|
+function inputClick(object, parameterName) {
|
|
|
+ // 获取当前聚焦的元素并移除焦点
|
|
|
+ const activeElement = document.activeElement
|
|
|
+ if (activeElement && typeof activeElement.blur === 'function') {
|
|
|
+ activeElement.blur()
|
|
|
+ }
|
|
|
+
|
|
|
+ richEditor.object = object
|
|
|
+ richEditor.parameterName = parameterName
|
|
|
+ richEditor.dialogVisible = true
|
|
|
+}
|
|
|
+
|
|
|
+function editorConfirm() {
|
|
|
+ console.log(richEditor)
|
|
|
+ let content = richEditor.instance.getContent()
|
|
|
+ richEditor.object[richEditor.parameterName] = content
|
|
|
+ richEditor.dialogVisible = false
|
|
|
+}
|
|
|
+
|
|
|
+function questionItemRemove(index) {
|
|
|
+ form.value.items.splice(index, 1)
|
|
|
+}
|
|
|
+
|
|
|
+function questionItemAdd() {
|
|
|
+ const items = form.value.items
|
|
|
+ let newLastPrefix
|
|
|
+ console.log('last', items)
|
|
|
+ if (items.length > 0) {
|
|
|
+ let last = items[items.length - 1]
|
|
|
+ newLastPrefix = String.fromCharCode(last.prefix.charCodeAt() + 1)
|
|
|
+ } else {
|
|
|
+ newLastPrefix = 'A'
|
|
|
+ }
|
|
|
+ items.push({ id: null, prefix: newLastPrefix, content: '' })
|
|
|
+}
|
|
|
+
|
|
|
+function submitForm() {
|
|
|
+ formRef.value.validate().then(valid => {
|
|
|
+ if (valid) {
|
|
|
+ formLoading.value = true
|
|
|
+ questionApi.edit(form).then(re => {
|
|
|
+ if (re.code === 1) {
|
|
|
+ store.dispatch('tagsView/delCurrentView').then(() => {
|
|
|
+ router.push('/exam/question/list')
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }).catch(e => {
|
|
|
+ console.error(e)
|
|
|
+ }).finally(() => {
|
|
|
+ formLoading.value = false
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+function resetForm() {
|
|
|
+ const lastId = form.id
|
|
|
+ formRef.value.resetFields()
|
|
|
+ Object.assign(form, {
|
|
|
+ id: null,
|
|
|
+ questionType: 1,
|
|
|
+ gradeLevel: null,
|
|
|
+ subjectId: null,
|
|
|
+ title: '',
|
|
|
+ items: [
|
|
|
+ { prefix: 'A', content: '' },
|
|
|
+ { prefix: 'B', content: '' },
|
|
|
+ { prefix: 'C', content: '' },
|
|
|
+ { prefix: 'D', content: '' }
|
|
|
+ ],
|
|
|
+ analyze: '',
|
|
|
+ correct: '',
|
|
|
+ score: '',
|
|
|
+ difficult: 0
|
|
|
+ })
|
|
|
+ form.id = lastId
|
|
|
+}
|
|
|
+
|
|
|
+function showQuestion() {
|
|
|
+ questionShow.dialog = true
|
|
|
+ questionShow.qType = form.value.questionType
|
|
|
+ console.log(form)
|
|
|
+ console.log(questionShow)
|
|
|
+ questionShow.question = form.value
|
|
|
+ form.value.items.forEach((item, index) => {
|
|
|
+ console.log(`选项 ${item.prefix} 的内容:`, item.content)
|
|
|
+ })
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.question-item-label {
|
|
|
+ margin-top: 10px;
|
|
|
+ margin-bottom: 10px !important;
|
|
|
+}
|
|
|
+
|
|
|
+.question-item-remove {
|
|
|
+ margin-left: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.question-item-content-input {
|
|
|
+ margin-left: 8px;
|
|
|
+ width: 60%;
|
|
|
+ height: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.question-item-span {
|
|
|
+ vertical-align: middle;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ font-weight: 700;
|
|
|
+ box-sizing: border-box;
|
|
|
+ margin-left: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.question-item-rate {
|
|
|
+ line-height: 2.5;
|
|
|
+}
|
|
|
+</style>
|