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.
 
 
 
 

644 lines
28 KiB

import React, { Component } from 'react';
import { Form, Input, Button, Radio, Checkbox, Select, message, Modal, Table } from 'antd';
import { getRandomQuestions, addExamPaper, editExamPaper, getExamPaperDetail} from 'api/examPaper';
import { getList ,findIndustry} from 'api/question';
import { dictionary } from "../../api/dict";
const { Option } = Select;
interface optionsState {
value: string;
label: string;
}
interface QuestionState {
id: string;
serviceTypeId: string;
questionTypes: string;
questionContent: string;
answerOptions: optionsState[];
answer: string | null;
}
interface States {
id: string| null;
isEdit: string| null;
num: number;
page: number;
total: number;
industryDict: any;
serviceTypeDict: any;
loading: boolean;
questions: QuestionState[];
isModalVisible: boolean;
selectedParams: any;
selectedQuestionList: QuestionState[];
questionSelectList: QuestionState[];
selectedRowKeys: string[]; // 修改为存储 id 的数组
}
class ExamPaperAdd extends Component<any, States> {
formRef: any;
formRefSub: any;
constructor(props: any) {
super(props);
this.formRef = React.createRef();
this.formRefSub = React.createRef();
this.state = {
id: null,
isEdit: null,
num: 10,
page: 1,
total: 0,
industryDict: undefined,
serviceTypeDict: undefined,
loading: false,
questions: [],
isModalVisible: false,
selectedParams: {},
selectedQuestionList: [],
questionSelectList: [],
selectedRowKeys: []
};
}
componentDidMount() {
this.handleFindDict();
const id = sessionStorage.getItem('id');
const isEdit= sessionStorage.getItem('isEdit');
this.setState({ id: id ,isEdit: isEdit});
sessionStorage.removeItem('id');
sessionStorage.removeItem('isEdit');
if(isEdit === 'true'){
this.handleGetDetail(id);
}
}
// 字典
handleFindDict() {
// 监管行业
findIndustry()
.then((res: any) => {
if (res.data) {
this.setState({ industryDict: res.data });
}
})
.catch(() => {
message.error("获取监管行业字典数据失败,请稍后重试");
});
// AQ服务类型
dictionary("serviceTypeDict")
.then((res) => {
if (res.data) {
this.setState({ serviceTypeDict: res.data });
}
})
.catch(() => {
message.error("获取AQ服务类型字典数据失败,请稍后重试");
});
}
// 试卷详情
handleGetDetail = (id: any) => {
getExamPaperDetail(id).then((res: any) => {
if (res.data) {
const newQuestions: QuestionState[] = res.data.data.map((questionData: any) => {
const options = questionData.options.split(',');
const answerOptions = options.map((option: any) => {
const [value, label] = option.split('.');
return { value, label };
});
return {
id: String(questionData.id),
serviceTypeId: String(questionData.serviceTypeId),
questionTypes: String(questionData.questionTypes),
questionContent: String(questionData.questionContent),
answerOptions: answerOptions,
answer: String(questionData.answer)
};
});
this.setState({ questions: newQuestions });
const formValues = {};
formValues['paperName'] = res.data.head.paperName;
formValues['industryId'] = String(res.data.head.industryId);
formValues['questionCount'] = res.data.head.questionCount;
formValues['totalScore'] = res.data.head.totalScore;
formValues['examDuration'] = res.data.head.examDuration;
formValues['durationType'] = String(res.data.head.durationType);
formValues['paperContent'] = res.data.head.paperContent;
this.formRef.current.setFieldsValue(formValues);
}
}).catch(() => {
message.error('获取题目详情失败,请重试');
});
};
// 随机生成
handleRandomQuestion = () => {
this.formRef.current.validateFields(['industryId', 'questionCount'])
.then((values: any) => {
const data = {
industryId: values.industryId,
questionCount: values.questionCount
};
getRandomQuestions(data)
.then((res: any) => {
if (res.data) {
if (res.data.length == 0) {
message.warning('题库题目不足');
this.setState({ questions: [] });
return;
}
const newQuestions: QuestionState[] = res.data.map((questionData: any) => {
const options = questionData.options.split(',');
const answerOptions = options.map((option: any) => {
const [value, label] = option.split('.');
return { value, label };
});
return {
id: String(questionData.id),
serviceTypeId: String(questionData.serviceTypeId),
questionTypes: String(questionData.questionTypes),
questionContent: String(questionData.questionContent),
answerOptions: answerOptions,
answer: String(questionData.answer)
};
});
this.setState({ questions: newQuestions });
message.success('成功获取题目');
} else {
message.error('未获取到随机题目');
}
})
.catch(() => {
message.error('获取随机题目失败');
});
})
.catch(() => { });
};
// 手动选题
handleOpenModal = () => {
const { questions, selectedQuestionList } = this.state;
this.formRef.current.validateFields(['industryId'])
.then((values: any) => {
const industryId = values.industryId;
const questionCount = values.questionCount;
this.setState({
isModalVisible: true,
selectedQuestionList: questions,
selectedParams: { selectedQuestionList, industryId, questionCount }
}, () => {
this.handleQuery(); // 打开模态框时执行查询
});
})
.catch(() => { });
};
// 关闭选题
handleCloseModal = () => {
this.setState({
isModalVisible: false,
selectedParams: {},
selectedQuestionList: [],
questionSelectList: [],
selectedRowKeys: [],
num: 10,
page: 1,
total: 0,
});
if (this.formRefSub.current) {
this.formRefSub.current.resetFields();
}
};
// 处理删除已选试题
handleDeleteQuestion = (record: QuestionState) => {
const { selectedQuestionList} = this.state;
const newQuestion = selectedQuestionList.filter(item => item.id!== record.id);
const newSelectedRowKeys = newQuestion.map(item => item.id);
this.setState({ selectedQuestionList: newQuestion, selectedRowKeys: newSelectedRowKeys });
};
// 处理查询
handleQuery = () => {
this.setState({ loading: true });
const values = this.formRefSub.current.getFieldsValue();
const { num, page, selectedParams } = this.state;
const industryId = selectedParams.industryId;
const data = {
...values,
industryId,
num,
page
};
getList(data)
.then((res: any) => {
if (res.data) {
this.setState({ total: res.data.total });
const newQuestions: QuestionState[] = res.data.data.map((questionData: any) => {
const options = questionData.options.split(',');
const answerOptions = options.map((option: any) => {
const [value, label] = option.split('.');
return { value, label };
});
return {
id: String(questionData.id),
serviceTypeId: String(questionData.serviceTypeId),
questionTypes: String(questionData.questionTypes),
questionContent: String(questionData.questionContent),
answerOptions: answerOptions,
answer: String(questionData.answer)
};
});
const { selectedQuestionList } = this.state;
const newSelectedRowKeys = selectedQuestionList.map(item => item.id);
this.setState({ questionSelectList: newQuestions, selectedRowKeys: newSelectedRowKeys });
}
})
.catch(() => {
message.error('获取数据失败');
})
.finally(() => {
this.setState({ loading: false });
});
};
// 确认
handleConfirmSelection = () => {
const { selectedQuestionList } = this.state;
this.setState({
questions: selectedQuestionList,
isModalVisible: false,
selectedParams: {},
selectedQuestionList: [],
questionSelectList: [],
selectedRowKeys: [],
num: 10,
page: 1,
total: 0,
});
if (this.formRefSub.current) {
this.formRefSub.current.resetFields();
}
this.formRef.current.setFieldsValue({ questionCount : selectedQuestionList.length });
};
// 保存试卷
handleSaveExamPaper = () => {
const { isEdit, id } = this.state;
this.formRef.current.validateFields()
.then((values: any) => {
const { questions } = this.state;
if (questions === null || questions.length === 0) {
message.error('请选择题目');
return;
}
const questionIds = questions.map(question => question.id);
const data = {
...values,
id,
questionIds
};
if (isEdit === 'true') {
editExamPaper(data)
.then((res) => {
const success = res["success"];
if (success) {
message.success('试卷更新成功');
this.props.history.push('/examPaperList');
} else {
message.error('试卷更新失败');
}
})
.catch(() => {
message.error('试卷更新时出错,请稍后重试');
})
} else {
addExamPaper(data)
.then((res) => {
const success = res["success"];
if (success) {
message.success('试卷保存成功');
this.props.history.push('/examPaperList');
} else {
message.error('试卷保存失败');
}
})
.catch(() => {
message.error('试卷保存时出错,请稍后重试');
})
}
});
};
render() {
const {
industryDict,
serviceTypeDict,
questions,
loading,
isModalVisible,
selectedQuestionList,
questionSelectList,
selectedRowKeys
} = this.state;
const changePage = (current: number, pageSize: number) => {
setTimeout(() => {
this.setState({ page: current, num: pageSize });
this.handleQuery();
}, 0);
};
const handleListQuestion = () => {
this.props.history.push('/examPaperList');
};
const columns: any = [
{ title: '序号', dataIndex: 'index', align: 'center', width: 60,
render: (_: number, __: number, index: number) => index + 1
},
{ title: 'AQ服务类型', dataIndex: 'serviceTypeId', key: 'serviceTypeId', align: 'center', width: 150,
render: (serviceTypeId: any) => {
const serviceType = serviceTypeDict?.find((item: { dictKey: string | number; dictValue: string }) => String(item.dictKey) === serviceTypeId);
return serviceType? serviceType.dictValue : serviceTypeId;
}
},
{ title: '题型', dataIndex: 'questionTypes', key: 'questionTypes', align: 'center', width: 80,
render: (questionTypes: any) => {
if (questionTypes === '1') {
return '单选题';
} else if (questionTypes === '2') {
return '多选题';
}
return questionTypes;
}
},
{ title: '题干', dataIndex: 'questionContent', key: 'questionContent', align: 'center', width: 450 },
{ title: '答案', dataIndex: 'answer', key: 'answer', align: 'center', width: 120 },
{ title: '操作', dataIndex: 'operation', align: 'center', width: 120,
render: (_: number, record: QuestionState) => (
<Button type="link" danger onClick={() => this.handleDeleteQuestion(record)}></Button>
)
}
];
const columnsWithoutOperation = columns.filter((column: any) => column.dataIndex!== 'operation');
return (
<div className="container">
<Form ref={this.formRef}>
<h3 style={{ fontWeight: 'bold' }}></h3>
<Form.Item
label="试卷名称:"
name="paperName"
style={{ width: 1190 }}
rules={[{ required: true, message: '请输入试卷名称' }]}
>
<Input placeholder="请输入试卷名称" />
</Form.Item>
<div style={{ display: 'flex', gap: 20 }}>
<Form.Item
label="监管行业:"
name={`industryId`}
rules={[{ required: true, message: '请选择监管行业' }]}
>
<Select placeholder="请选择监管行业" style={{ width: 240 }} allowClear>
{industryDict && industryDict.length > 0? (
(() => {
let rows = [];
for (let i = 0; i < industryDict.length; i++) {
const item = industryDict[i];
rows.push(
<Option value={item.industryId}>{item.industryName}</Option>
);
}
return rows;
})()
) : (
<Option disabled></Option>
)}
</Select>
</Form.Item>
<Form.Item
label="题目数量:"
name="questionCount"
style={{ width: 240 }}
rules={[{ required: true, message: '请输入题目数量' }]}
>
<Input type="number" style={{ textAlign: 'right' }} placeholder="请输入题目数量" min={1} />
</Form.Item>
<Form.Item
label="总分值:"
name="totalScore"
style={{ width: 240 }}
rules={[{ required: true, message: '请输入总分值' }]}
>
<Input type="number" style={{ textAlign: 'right' }} placeholder="请输入总分值" min={1} />
</Form.Item>
<Form.Item
label="考试时长:"
name="examDuration"
style={{ width: 240 }}
rules={[{ required: true, message: '请输入考试时长' }]}
>
<Input type="number" style={{ textAlign: 'right' }} placeholder="请输入考试时长" min={1} />
</Form.Item>
<Form.Item
name="durationType"
style={{ width: 90 }}
rules={[{ required: true, message: '请输入考试时长' }]}
>
<Select>
<Option value="1">(min)</Option>
<Option value="2">(h)</Option>
</Select>
</Form.Item>
</div>
<Form.Item
label="内容描述:"
name="paperContent"
style={{ width: 1190 }}
rules={[{ required: true, message: '请输入内容描述' }]}
>
<Input.TextArea placeholder="请输入内容描述" />
</Form.Item>
<div style={{ display: 'flex' }}>
<h3 style={{ fontWeight: 'bold' }}></h3>
<div>
<Button type="link" onClick={this.handleRandomQuestion}>
</Button>
<Button type="link" onClick={this.handleOpenModal}>
</Button>
</div>
</div>
{questions.map((question, index) => (
<div
style={{
border: '1px solid #e8e8e8',
padding: 10,
marginBottom: 10
}}
>
<span style={{ fontWeight: 'bold' }}>{index + 1}. {question.questionContent}</span>
<Form.Item>
{question.questionTypes === '1'? (
<Radio.Group value={question.answer}>
{question.answerOptions.map((option) => (
<Radio value={option.value}>
{option.value}. {option.label}
</Radio>
))}
</Radio.Group>
) : (
<Checkbox.Group value={question.answer? question.answer.split(',') : []}>
{question.answerOptions.map((option) => (
<Checkbox value={option.value}>
{option.value}. {option.label}
</Checkbox>
))}
</Checkbox.Group>
)}
</Form.Item>
</div>
))}
<div
style={{
textAlign: 'right',
position: 'fixed',
bottom: 10,
right: 10,
width: '100%',
backgroundColor: 'white',
zIndex: 1000
}}
>
<Button type="default" htmlType="button" onClick={handleListQuestion} style={{ marginRight: 10 }}>
</Button>
<Button type="primary" htmlType="submit" onClick={this.handleSaveExamPaper}>
</Button>
</div>
</Form>
<Modal
title="选择试题"
open={isModalVisible}
maskClosable={false}
onCancel={this.handleCloseModal}
footer={[
<Button key="cancel" onClick={this.handleCloseModal}>
</Button>,
<Button key="ok" type="primary" onClick={this.handleConfirmSelection}>
</Button>
]}
width={1100}
style={{ top: 20 }}
>
<div>
<h3 style={{ fontWeight: 'bold' }}></h3>
<Table
dataSource={selectedQuestionList}
columns={columns}
bordered={true}
scroll={{ y: 200 }}
size={'small'}
/>
</div>
<div style={{ marginTop: '20px' }}>
<h3 style={{ fontWeight: 'bold' }}></h3>
<Form
className="filter"
layout="inline"
ref={this.formRefSub}
>
<Form.Item
label="AQ服务类型:"
name="serviceTypeId"
>
<Select placeholder="请选择AQ服务类型"
style={{ width: 240 }}
allowClear>
{
serviceTypeDict && serviceTypeDict.length > 0?
(() => {
let rows = [];
for (let i = 0; i < serviceTypeDict.length; i++) {
const item = serviceTypeDict[i];
rows.push(
<Option value={item.dictKey}>{item.dictValue}</Option>
);
}
return rows;
})()
:
<Option disabled></Option>
}
</Select>
</Form.Item>
<Form.Item
label="题干条件:"
name="questionContent"
>
<Input placeholder="请输入题干条件" style={{ width: 500 }}/>
</Form.Item>
<Form.Item>
<Button type="primary" onClick={this.handleQuery}></Button>
</Form.Item>
</Form>
</div>
<Table
dataSource={questionSelectList}
columns={columnsWithoutOperation}
bordered={true}
size={'small'}
rowKey="id"
scroll={{ y: 200 }}
loading={loading}
rowSelection={{
selectedRowKeys: selectedRowKeys,
onChange: (newSelectedRowKeys, selectedRows) => {
const { selectedQuestionList,questionSelectList } = this.state;
const newSelectedQuestionList = selectedRows.reduce((acc, row) => {
if (!acc.some(item => item.id === row.id)) {
acc.push(row);
}
return acc;
}, [...selectedQuestionList]);
const deselectedIds = questionSelectList
.filter(item =>!newSelectedRowKeys.includes(item.id))
.map(item => item.id);
const finalSelectedQuestionList = newSelectedQuestionList.filter(
item =>!deselectedIds.includes(item.id)
);
const selectedRowKeys = finalSelectedQuestionList.map(item => String(item.id));
this.setState({
selectedQuestionList: finalSelectedQuestionList,
selectedRowKeys: selectedRowKeys
});
},
getCheckboxProps: () => ({
disabled: false
})
}}
pagination={{
total: this.state.total,
current: this.state.page,
showQuickJumper: true,
showSizeChanger: true,
showTotal: (total) => `${total}`,
onChange: changePage
}}
/>
</Modal>
</div>
);
}
}
export default ExamPaperAdd;