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

<!-- 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>