|
|
<script setup>
|
|
|
/**
|
|
|
* name:
|
|
|
* user:sa0ChunLuyu
|
|
|
* date:2024年10月12日 16:29:26
|
|
|
*/
|
|
|
import { ref, onMounted, nextTick } from 'vue'
|
|
|
import $router from '@/router'
|
|
|
import { onBeforeRouteUpdate } from 'vue-router'
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
import {
|
|
|
QuestionQuestionSelectAction,
|
|
|
QuestionItemSelectAction,
|
|
|
QuestionQuestionCreateAction,
|
|
|
QuestionQuestionUpdateAction,
|
|
|
QuestionQuestionDeleteAction,
|
|
|
QuestionQuestionListAction
|
|
|
} from '@/api/api.js'
|
|
|
|
|
|
const default_page_options = {
|
|
|
search: '',
|
|
|
page: 1
|
|
|
}
|
|
|
const page_options = ref(JSON.parse(JSON.stringify(default_page_options)))
|
|
|
onBeforeRouteUpdate((to) => {
|
|
|
routerChange(to.query)
|
|
|
})
|
|
|
const table_list = ref([])
|
|
|
const last_page = ref(0)
|
|
|
const QuestionQuestionList = async () => {
|
|
|
const response = await QuestionQuestionListAction(page_options.value)
|
|
|
if (response.status !== 'no') {
|
|
|
table_list.value = response.data.list.data.map((item) => {
|
|
|
return {
|
|
|
...item,
|
|
|
option: JSON.parse(item.option)
|
|
|
}
|
|
|
})
|
|
|
last_page.value = response.data.list.last_page
|
|
|
} else {
|
|
|
ElMessage.error(response.msg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const routerChange = (query) => {
|
|
|
page_options.value = {
|
|
|
search: query.search || default_page_options.search,
|
|
|
page: Number(query.page) || default_page_options.page
|
|
|
}
|
|
|
QuestionQuestionList()
|
|
|
}
|
|
|
|
|
|
const searchClick = (page = 1) => {
|
|
|
page_options.value.page = page
|
|
|
$router.push({
|
|
|
query: JSON.parse(JSON.stringify(page_options.value))
|
|
|
})
|
|
|
}
|
|
|
const select_option = {
|
|
|
value: [
|
|
|
{ content: 'A. ', type: 'items', items: [], questions: [], score: 0 },
|
|
|
{ content: 'B. ', type: 'items', items: [], questions: [], score: 0 },
|
|
|
{ content: 'C. ', type: 'items', items: [], questions: [], score: 0 }
|
|
|
]
|
|
|
}
|
|
|
const input_option = {
|
|
|
value: '',
|
|
|
placeholder: '请输入选项内容'
|
|
|
}
|
|
|
const edit_data_default = {
|
|
|
id: 0,
|
|
|
question: '',
|
|
|
type: 'input',
|
|
|
option: {
|
|
|
input: JSON.parse(JSON.stringify(input_option)),
|
|
|
select: JSON.parse(JSON.stringify(select_option))
|
|
|
}
|
|
|
}
|
|
|
const edit_data = ref(JSON.parse(JSON.stringify(edit_data_default)))
|
|
|
const edit_show = ref(false)
|
|
|
const createClick = () => {
|
|
|
updateClick(edit_data_default)
|
|
|
}
|
|
|
const updateClick = (row) => {
|
|
|
edit_data.value = JSON.parse(JSON.stringify(row))
|
|
|
edit_show.value = true
|
|
|
}
|
|
|
const editDoneClick = async () => {
|
|
|
const $func =
|
|
|
edit_data.value.id !== 0 ? QuestionQuestionUpdateAction : QuestionQuestionCreateAction
|
|
|
const response = await $func({
|
|
|
...edit_data.value,
|
|
|
option: JSON.stringify(edit_data.value.option)
|
|
|
})
|
|
|
if (response.status !== 'no') {
|
|
|
edit_show.value = false
|
|
|
await QuestionQuestionList()
|
|
|
} else {
|
|
|
ElMessage.error(response.msg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const QuestionQuestionDelete = async (id) => {
|
|
|
const response = await QuestionQuestionDeleteAction({ id })
|
|
|
if (response.status !== 'no') {
|
|
|
await QuestionQuestionList()
|
|
|
} else {
|
|
|
ElMessage.error(response.msg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const deleteClick = (id) => {
|
|
|
ElMessageBox.confirm('是否确认删除该题目?', '提示', {
|
|
|
confirmButtonText: '确认',
|
|
|
cancelButtonText: '取消',
|
|
|
type: 'warning'
|
|
|
})
|
|
|
.then(() => {
|
|
|
QuestionQuestionDelete(id)
|
|
|
})
|
|
|
.catch(() => {})
|
|
|
}
|
|
|
const edit_item_data = ref({
|
|
|
active: 0,
|
|
|
items: []
|
|
|
})
|
|
|
const edit_item_show = ref(false)
|
|
|
const question_list = ref([])
|
|
|
const QuestionQuestionSelect = async () => {
|
|
|
const response = await QuestionQuestionSelectAction()
|
|
|
if (response.status !== 'no') {
|
|
|
question_list.value = response.data.list
|
|
|
} else {
|
|
|
ElMessage.error(response.msg)
|
|
|
}
|
|
|
}
|
|
|
const editItemClick = async (index) => {
|
|
|
const type = edit_data.value.option.select.value[index].type
|
|
|
if (type === 'questions') {
|
|
|
await QuestionQuestionSelect()
|
|
|
}
|
|
|
await nextTick(() => {
|
|
|
edit_item_data.value = {
|
|
|
active: index,
|
|
|
items: JSON.parse(JSON.stringify(edit_data.value.option.select.value[index][type]))
|
|
|
}
|
|
|
edit_item_show.value = true
|
|
|
})
|
|
|
}
|
|
|
const editItemDoneClick = () => {
|
|
|
const type = edit_data.value.option.select.value[edit_item_data.value.active].type
|
|
|
edit_data.value.option.select.value[edit_item_data.value.active][type] = JSON.parse(
|
|
|
JSON.stringify(edit_item_data.value.items)
|
|
|
)
|
|
|
edit_item_show.value = false
|
|
|
}
|
|
|
const filterMethod = (query, item) => {
|
|
|
const type = edit_data.value.option.select.value[edit_item_data.value.active].type
|
|
|
if (type === 'items') {
|
|
|
return item.name.toLowerCase().includes(query.toLowerCase())
|
|
|
} else {
|
|
|
return item.question.toLowerCase().includes(query.toLowerCase())
|
|
|
}
|
|
|
}
|
|
|
const item_list = ref([])
|
|
|
const QuestionItemSelect = async () => {
|
|
|
const response = await QuestionItemSelectAction()
|
|
|
if (response.status !== 'no') {
|
|
|
item_list.value = response.data.list
|
|
|
} else {
|
|
|
ElMessage.error(response.msg)
|
|
|
}
|
|
|
}
|
|
|
const moveQuestionClick = (index, type) => {
|
|
|
if (edit_data.value.option.select.value.length - 1 >= index + type) {
|
|
|
const question = edit_data.value.option.select.value[index]
|
|
|
edit_data.value.option.select.value[index] = JSON.parse(
|
|
|
JSON.stringify(edit_data.value.option.select.value[index + type])
|
|
|
)
|
|
|
edit_data.value.option.select.value[index + type] = JSON.parse(JSON.stringify(question))
|
|
|
}
|
|
|
}
|
|
|
const delQuestionClick = (index) => {
|
|
|
edit_data.value.option.select.value.splice(index, 1)
|
|
|
}
|
|
|
const addQuestionClick = () => {
|
|
|
edit_data.value.option.select.value.push({ content: '', type: 'items', items: [], questions: [] })
|
|
|
}
|
|
|
const question_type_map = {
|
|
|
select: '选择题',
|
|
|
input: '输入框'
|
|
|
}
|
|
|
onMounted(() => {
|
|
|
routerChange($router.currentRoute.value.query)
|
|
|
QuestionItemSelect()
|
|
|
})
|
|
|
</script>
|
|
|
<template>
|
|
|
<div>
|
|
|
<el-dialog
|
|
|
v-model="edit_item_show"
|
|
|
title="关联管理"
|
|
|
width="610px"
|
|
|
:close-on-click-modal="false"
|
|
|
:close-on-press-escape="false"
|
|
|
:show-close="false"
|
|
|
>
|
|
|
<div>
|
|
|
<el-transfer
|
|
|
v-if="!!edit_item_show"
|
|
|
:titles="['可选', '已选']"
|
|
|
:props="{
|
|
|
key: 'id',
|
|
|
label:
|
|
|
edit_data.option.select.value[edit_item_data.active].type === 'items'
|
|
|
? 'name'
|
|
|
: 'question'
|
|
|
}"
|
|
|
v-model="edit_item_data.items"
|
|
|
filterable
|
|
|
:filter-method="filterMethod"
|
|
|
filter-placeholder="搜索"
|
|
|
:data="
|
|
|
edit_data.option.select.value[edit_item_data.active].type === 'items'
|
|
|
? item_list
|
|
|
: question_list
|
|
|
"
|
|
|
/>
|
|
|
</div>
|
|
|
<template #footer>
|
|
|
<div class="dialog-footer">
|
|
|
<el-button @click="editItemDoneClick()" type="primary">确定</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
<el-dialog v-model="edit_show" :title="`${!!edit_data.id ? '编辑' : '新建'}`" width="1000px">
|
|
|
<div>
|
|
|
<el-form label-width="150">
|
|
|
<el-form-item label="题目">
|
|
|
<el-input v-model="edit_data.question" placeholder="请输入题目"></el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="题目类型">
|
|
|
<el-select v-model="edit_data.type" placeholder="请选择题目类型">
|
|
|
<el-option label="选择题" value="select"></el-option>
|
|
|
<el-option label="输入框" value="input"></el-option>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<template v-if="edit_data.type === 'input'">
|
|
|
<el-form-item label="题目配置">
|
|
|
<div>
|
|
|
<div class="select_item_wrapper">
|
|
|
<el-input
|
|
|
class="select_input_wrapper"
|
|
|
v-model="edit_data.option.input.value"
|
|
|
placeholder="请输入默认值"
|
|
|
></el-input>
|
|
|
<el-input
|
|
|
class="select_input_wrapper"
|
|
|
v-model="edit_data.option.input.placeholder"
|
|
|
placeholder="请输入占位符"
|
|
|
></el-input>
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
</template>
|
|
|
<template v-else-if="edit_data.type === 'select'">
|
|
|
<el-form-item label="题目配置">
|
|
|
<div>
|
|
|
<div
|
|
|
class="select_item_wrapper"
|
|
|
v-for="(_, k) in edit_data.option.select.value"
|
|
|
:key="k"
|
|
|
>
|
|
|
<el-input
|
|
|
class="select_input_wrapper"
|
|
|
v-model="edit_data.option.select.value[k].content"
|
|
|
placeholder="请输入"
|
|
|
></el-input>
|
|
|
<el-select
|
|
|
class="select_select_wrapper"
|
|
|
v-model="edit_data.option.select.value[k].type"
|
|
|
placeholder="请选择题目类型"
|
|
|
>
|
|
|
<el-option label="项目" value="items"></el-option>
|
|
|
<el-option label="题目" value="questions"></el-option>
|
|
|
<el-option label="分数" value="score"></el-option>
|
|
|
</el-select>
|
|
|
<template v-if="edit_data.option.select.value[k].type === 'score'">
|
|
|
<el-input-number
|
|
|
v-model="edit_data.option.select.value[k].score"
|
|
|
></el-input-number>
|
|
|
</template>
|
|
|
<template v-else>
|
|
|
<span style="margin-right: 10px"
|
|
|
>{{
|
|
|
edit_data.option.select.value[k].type === 'items'
|
|
|
? edit_data.option.select.value[k].items.length
|
|
|
: edit_data.option.select.value[k].questions.length
|
|
|
}}个{{
|
|
|
edit_data.option.select.value[k].type === 'items' ? '项目' : '题目'
|
|
|
}}</span
|
|
|
>
|
|
|
<el-button type="primary" size="small" @click="editItemClick(k)">
|
|
|
编辑{{ edit_data.option.select.value[k].type === 'items' ? '项目' : '题目' }}
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
:disabled="k === 0"
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
@click="moveQuestionClick(k, -1)"
|
|
|
>↑
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
:disabled="k === edit_data.option.select.value.length - 1"
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
@click="moveQuestionClick(k, 1)"
|
|
|
>↓
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
:disabled="edit_data.option.select.value.length === 1"
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
@click="delQuestionClick(k)"
|
|
|
>X
|
|
|
</el-button>
|
|
|
</template>
|
|
|
</div>
|
|
|
<div>
|
|
|
<el-button type="primary" size="small" @click="addQuestionClick()"
|
|
|
>添加选项</el-button
|
|
|
>
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
</template>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
<template #footer>
|
|
|
<span class="dialog-footer">
|
|
|
<el-button @click="edit_show = false">取消</el-button>
|
|
|
<el-button type="primary" @click="editDoneClick()">确定</el-button>
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
<div class="head">
|
|
|
<div class="head">
|
|
|
<el-row>
|
|
|
<el-form-item>
|
|
|
<el-input v-model="page_options.search" placeholder="搜索题目" />
|
|
|
</el-form-item>
|
|
|
<el-button type="primary" @click="searchClick()" style="margin-left: 10px"
|
|
|
>查询</el-button
|
|
|
>
|
|
|
<el-button type="success" @click="createClick()" style="margin-left: 10px"
|
|
|
>添加</el-button
|
|
|
>
|
|
|
</el-row>
|
|
|
</div>
|
|
|
</div>
|
|
|
<el-table
|
|
|
:data="table_list"
|
|
|
style="width: 100%"
|
|
|
row-key="id"
|
|
|
:tooltip-options="{
|
|
|
popperClass: 'popper_class_wrapper'
|
|
|
}"
|
|
|
>
|
|
|
<el-table-column prop="id" label="ID" width="100" />
|
|
|
<el-table-column prop="question" label="题目" width="200" show-overflow-tooltip />
|
|
|
<el-table-column label="类型" width="100">
|
|
|
<template #default="scope">
|
|
|
{{ question_type_map[scope.row.type] }}
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="题目配置">
|
|
|
<template #default="scope">
|
|
|
<div v-if="scope.row.type === 'input'" class="select_item_wrapper">
|
|
|
<span class="title_wrapper">占位符:</span
|
|
|
><span style="margin: 0 10px">{{ scope.row.option.input.placeholder }}</span>
|
|
|
<span v-if="!!scope.row.option.input.value" class="title_wrapper">默认值:</span
|
|
|
><span style="margin: 0 10px">{{ scope.row.option.input.value }}</span>
|
|
|
</div>
|
|
|
<div v-else-if="scope.row.type === 'select'">
|
|
|
<div
|
|
|
class="select_item_wrapper"
|
|
|
v-for="(i, k) in scope.row.option.select.value"
|
|
|
:key="k"
|
|
|
>
|
|
|
<span style="margin-right: 10px; width: 400px">{{ i.content }}</span>
|
|
|
<span class="title_wrapper">带出:</span>
|
|
|
<span v-if="scope.row.option.select.value[k].type === 'items'">项目</span>
|
|
|
<span v-else-if="scope.row.option.select.value[k].type === 'questions'">题目</span>
|
|
|
<span v-else-if="scope.row.option.select.value[k].type === 'score'">分数</span>
|
|
|
<span v-if="scope.row.option.select.value[k].type === 'score'" style="margin: 0 5px">{{
|
|
|
scope.row.option.select.value[k][scope.row.option.select.value[k].type]
|
|
|
}}</span>
|
|
|
<span v-else style="margin: 0 5px">{{
|
|
|
scope.row.option.select.value[k][scope.row.option.select.value[k].type].length
|
|
|
}}</span>
|
|
|
<span>{{ scope.row.option.select.value[k].type === 'score' ? '分' : '个' }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="操作" width="140">
|
|
|
<template #default="scope">
|
|
|
<el-button type="primary" @click="updateClick(scope.row)" size="small">修改</el-button>
|
|
|
<el-button type="danger" @click="deleteClick(scope.row.id)" size="small">删除</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
<div class="page">
|
|
|
<el-pagination
|
|
|
v-if="last_page > 0"
|
|
|
:current-page="page_options.page"
|
|
|
mt-2
|
|
|
background
|
|
|
layout="prev, pager, next"
|
|
|
:page-count="last_page"
|
|
|
@update:current-page="searchClick"
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<style>
|
|
|
.popper_class_wrapper {
|
|
|
width: 300px;
|
|
|
}
|
|
|
</style>
|
|
|
<style scoped>
|
|
|
.title_wrapper {
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
.select_input_wrapper {
|
|
|
width: 300px;
|
|
|
margin-right: 10px;
|
|
|
}
|
|
|
|
|
|
.select_select_wrapper {
|
|
|
width: 80px;
|
|
|
margin-right: 10px;
|
|
|
}
|
|
|
|
|
|
.select_item_wrapper {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
margin-bottom: 5px;
|
|
|
}
|
|
|
|
|
|
.page {
|
|
|
display: flex;
|
|
|
justify-content: flex-end;
|
|
|
margin-top: 10px;
|
|
|
}
|
|
|
</style>
|