You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
465 lines
13 KiB
465 lines
13 KiB
<!-- src/components/Question/QuestionSearch.vue -->
|
|
<template>
|
|
<div class="question-search-container">
|
|
<div class="top">
|
|
<h2>题库管理</h2>
|
|
</div>
|
|
<!-- 搜索区域容器 -->
|
|
<div class="search-area">
|
|
<!-- 题目类型筛选项 -->
|
|
<div class="search-item">
|
|
<h3>题目类型</h3>
|
|
<select v-model="searchForm.questionType">
|
|
<option value="">全部</option>
|
|
<option>股票知识</option>
|
|
<option>企业文化</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- 题干关键词搜索项 -->
|
|
<div class="search-item">
|
|
<h3>题干查找</h3>
|
|
<input type="text" placeholder="请输入题干关键词" v-model="searchForm.keyword" />
|
|
</div>
|
|
|
|
<!-- 课程推荐筛选项 -->
|
|
<div class="search-item">
|
|
<h3>推荐系列</h3>
|
|
<select v-model="searchForm.course">
|
|
<option value="">全部</option>
|
|
<option>量能擒牛</option>
|
|
<option>价格破译</option>
|
|
<option>量价时空综合</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- 操作按钮组 -->
|
|
<div class="btn-group">
|
|
<button class="btn-red" @click="handleSearch">查找</button>
|
|
<button class="btn-red" @click="showAddModal = true">新增题目</button>
|
|
<button class="btn-red" @click="exportExcel">Excel导出</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 新增题目弹窗 -->
|
|
<div v-if="showAddModal" class="modal-overlay">
|
|
<div class="modal-content" @click.stop>
|
|
<div class="modal-header">
|
|
<h3>新增题目</h3>
|
|
<button class="close-btn" @click="closeModal">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-row">
|
|
<label>题目类型</label>
|
|
<select v-model="newQuestion.questionTypeName">
|
|
<option value="股票知识">股票知识</option>
|
|
<option value="企业文化">企业文化</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<label>题干</label>
|
|
<textarea v-model="newQuestion.stem" placeholder="请输入题目内容" rows="4"
|
|
style="width: 545px; height: 120px;"
|
|
></textarea>
|
|
</div>
|
|
|
|
<div class="form-row-options">
|
|
<div class="option-group">
|
|
<label>选项A</label>
|
|
<input
|
|
type="text"
|
|
v-model="newQuestion.optionA"
|
|
placeholder="请输入选项A"
|
|
style="width: 280px; height: 40px;"
|
|
/>
|
|
</div>
|
|
<div class="option-group">
|
|
<label>选项B</label>
|
|
<input type="text" v-model="newQuestion.optionB" placeholder="请输入选项B" style="width: 280px; height: 40px;"/>
|
|
</div>
|
|
<div class="option-group">
|
|
<label>选项C</label>
|
|
<input type="text" v-model="newQuestion.optionC" placeholder="请输入选项C" style="width: 280px; height: 40px;"/>
|
|
</div>
|
|
<div class="option-group">
|
|
<label>选项D</label>
|
|
<input type="text" v-model="newQuestion.optionD" placeholder="请输入选项D" style="width: 280px; height: 40px;"/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<label>正确答案</label>
|
|
<select v-model="newQuestion.correctAnswer">
|
|
<option value="A">A</option>
|
|
<option value="B">B</option>
|
|
<option value="C">C</option>
|
|
<option value="D">D</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<label>推荐系列</label>
|
|
<select v-model="newQuestion.recommendedCourse">
|
|
<option value="量能擒牛">量能擒牛</option>
|
|
<option value="价格破译">价格破译</option>
|
|
<option value="量价时空综合">量价时空综合</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn-red" @click="addQuestion">确定</button>
|
|
<button class="btn-red" @click="closeModal">取消</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { getQuestions } from '@/api/question.js';
|
|
import axios from 'axios';
|
|
// import { Message } from 'element-ui'
|
|
|
|
export default {
|
|
name: 'QuestionSearch',
|
|
data() {
|
|
return {
|
|
searchForm: {
|
|
questionType: '',
|
|
keyword: '',
|
|
course: ''
|
|
},
|
|
showAddModal: false,
|
|
newQuestion: {
|
|
id: 0,
|
|
stem: '',
|
|
optionA: '',
|
|
optionB: '',
|
|
optionC: '',
|
|
optionD: '',
|
|
correctAnswer: 'A',
|
|
questionTypeName: '股票知识',
|
|
recommendedCourse: '量能擒牛'
|
|
},
|
|
currentPage: 1, // 当前页码
|
|
total: 0 // 总记录数
|
|
};
|
|
},
|
|
methods: {
|
|
async handleSearch(page = 1) {
|
|
try {
|
|
this.currentPage = page; // 更新当前页码
|
|
const params = new URLSearchParams();
|
|
params.append('page', page); // 使用传入的页码
|
|
params.append('page_size', 20);
|
|
|
|
// 题目类型映射为 id
|
|
const questionTypeIdMap = {
|
|
'股票知识': 1,
|
|
'企业文化': 2
|
|
};
|
|
if (this.searchForm.questionType) {
|
|
params.append('question_type_id', questionTypeIdMap[this.searchForm.questionType]);
|
|
}
|
|
|
|
// 推荐系列映射为 id
|
|
const courseRecommendationIdMap = {
|
|
'量能擒牛': 1,
|
|
'价格破译': 2,
|
|
'量价时空综合': 3
|
|
};
|
|
if (this.searchForm.course) {
|
|
params.append('course_recommendation_id', courseRecommendationIdMap[this.searchForm.course]);
|
|
}
|
|
|
|
// 题干关键词模糊查询
|
|
if (this.searchForm.keyword) {
|
|
params.append('stem', this.searchForm.keyword);
|
|
}
|
|
|
|
const response = await getQuestions(params);
|
|
|
|
// if (response.data.code === 200) {
|
|
// // 包装数据以便传递分页信息
|
|
// const resultData = {
|
|
// list: response.data.data.list,
|
|
// total: response.data.data.total || []
|
|
// };
|
|
// this.$emit('search-result', resultData);
|
|
// this.total = response.data.data.total || 0;
|
|
// } else {
|
|
// alert('搜索失败:' + response.data.msg);
|
|
// }
|
|
if (response.data.code === 200) {
|
|
const list = response.data.data.list || [];
|
|
|
|
const totalRaw = response.data.data.total;
|
|
const total = Number.isFinite(Number(totalRaw)) ? Number(totalRaw) : 1;
|
|
|
|
const resultData = { list, total };
|
|
|
|
this.$emit('search-result', resultData);
|
|
this.total = total;
|
|
} else {
|
|
alert('搜索失败:' + response.data.msg);
|
|
}
|
|
} catch (error) {
|
|
console.error('搜索失败:', error);
|
|
alert('网络错误,请检查连接!');
|
|
}
|
|
},
|
|
|
|
async addQuestion() {
|
|
// 表单验证
|
|
if (!this.newQuestion.stem || !this.newQuestion.optionA || !this.newQuestion.optionB ||
|
|
!this.newQuestion.optionC || !this.newQuestion.optionD || !this.newQuestion.correctAnswer || !this.newQuestion.recommendedCourse) {
|
|
alert('请填写所有必填项!');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// 构造请求参数
|
|
const params = new URLSearchParams();
|
|
params.append('id', this.newQuestion.id);
|
|
params.append('stem', this.newQuestion.stem);
|
|
params.append('A', this.newQuestion.optionA);
|
|
params.append('B', this.newQuestion.optionB);
|
|
params.append('C', this.newQuestion.optionC);
|
|
params.append('D', this.newQuestion.optionD);
|
|
params.append('correct_answer', this.newQuestion.correctAnswer);
|
|
params.append('question_type_id', this.newQuestion.questionTypeName === '股票知识' ? 1 : 2);
|
|
params.append('course_recommendation_id',
|
|
this.newQuestion.recommendedCourse === '量能擒牛' ? 1 :
|
|
this.newQuestion.recommendedCourse === '价格破译' ? 2 : 3 );
|
|
|
|
// 发送请求
|
|
// const response = await axios.post('/admin/questions/update', params, {
|
|
// headers: {
|
|
// 'Content-Type': 'application/x-www-form-urlencoded'
|
|
// }
|
|
// });
|
|
//发送请求
|
|
console.log(params);
|
|
const response = await axios.post('http://192.168.40.41:8000/admin/questions/update',params,
|
|
{
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
console.log(response.data);
|
|
|
|
if (response.data.code === 200) {
|
|
this.closeModal();
|
|
console.log('第二步');
|
|
this.$emit('question-added');
|
|
console.log('第三步');
|
|
this.$message({
|
|
message: '添加题目成功!',
|
|
type: 'success'
|
|
});
|
|
console.log('第四步');
|
|
} else {
|
|
alert('添加题目失败:' + response.data.msg);
|
|
}
|
|
} catch (error) {
|
|
console.error('添加题目失败:', error);
|
|
alert('网络错误,请检查连接!');
|
|
}
|
|
},
|
|
|
|
// 新增:处理分页搜索
|
|
async handlePageChange(page) {
|
|
await this.handleSearch(page);
|
|
},
|
|
|
|
async exportExcel() {
|
|
try{
|
|
// 构造包含筛选条件的导出参数
|
|
const exportParams = {};
|
|
|
|
// 添加题目类型筛选条件
|
|
const questionTypeIdMap = {
|
|
'股票知识': 1,
|
|
'企业文化': 2
|
|
};
|
|
if (this.searchForm.questionType) {
|
|
exportParams.question_type_id = questionTypeIdMap[this.searchForm.questionType];
|
|
}
|
|
|
|
// 添加推荐系列筛选条件
|
|
const courseRecommendationIdMap = {
|
|
'量能擒牛': 1,
|
|
'价格破译': 2,
|
|
'量价时空综合': 3
|
|
};
|
|
if (this.searchForm.course) {
|
|
exportParams.course_recommendation_id = courseRecommendationIdMap[this.searchForm.course];
|
|
}
|
|
|
|
// 添加题干关键词筛选条件
|
|
if (this.searchForm.keyword) {
|
|
exportParams.stem = this.searchForm.keyword;
|
|
}
|
|
|
|
// 发送导出请求,包含筛选条件
|
|
const response = await axios.post(
|
|
'http://192.168.40.41:8000/admin/questions/export',
|
|
exportParams,
|
|
{ responseType: 'blob' }
|
|
);
|
|
const url = window.URL.createObjectURL(new Blob([response.data]));
|
|
const link = document.createElement('a');
|
|
link.href = url;
|
|
link.setAttribute('download', '题库详细数据表.xlsx');
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
window.URL.revokeObjectURL(url);
|
|
alert('导出成功!');
|
|
}catch (error) {
|
|
console.error('导出 Excel 失败:', error);
|
|
alert('网络错误,请检查连接!');
|
|
}
|
|
},
|
|
closeModal() {
|
|
this.showAddModal = false;
|
|
console.log('关闭弹窗 第一步');
|
|
},
|
|
|
|
resetForm() {
|
|
this.newQuestion = {
|
|
id: 0,
|
|
stem: '',
|
|
optionA: '',
|
|
optionB: '',
|
|
optionC: '',
|
|
optionD: '',
|
|
correctAnswer: 'A',
|
|
questionTypeName: '股票知识',
|
|
recommendedCourse: '量能擒牛'
|
|
};
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
.top{
|
|
padding: 20px 0px;
|
|
}
|
|
/* 弹窗样式 */
|
|
.modal-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.modal-content {
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
width: 620px;
|
|
height: 760px;
|
|
max-width: 90%;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.modal-header {
|
|
padding: 20px;
|
|
border-bottom: 1px solid #eee;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.modal-header h3 {
|
|
margin: 0;
|
|
font-size: 18px;
|
|
color: #333;
|
|
}
|
|
|
|
.close-btn {
|
|
background: none;
|
|
border: none;
|
|
font-size: 24px;
|
|
cursor: pointer;
|
|
color: #666;
|
|
padding: 5px;
|
|
border-radius: 50%;
|
|
transition: color 0.2s;
|
|
}
|
|
|
|
.close-btn:hover {
|
|
color: #e74c3c;
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 20px;
|
|
max-height: 600px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.form-row {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.form-row label {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
font-weight: 500;
|
|
color: #333;
|
|
}
|
|
|
|
.form-row select,
|
|
.form-row input[type="text"],
|
|
.form-row textarea {
|
|
width: 100%;
|
|
padding: 10px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.form-row textarea {
|
|
resize: vertical;
|
|
}
|
|
|
|
.form-row-options {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 16px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.option-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.modal-footer {
|
|
padding: 20px;
|
|
border-top: 1px solid #eee;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 16px;
|
|
}
|
|
|
|
/* 响应式设计 */
|
|
@media (max-width: 768px) {
|
|
.modal-content {
|
|
width: 90%;
|
|
}
|
|
|
|
.form-row-options {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style>
|