parent
7ecca9ec82
commit
daf10d7133
6 changed files with 1415 additions and 0 deletions
@ -0,0 +1,82 @@ |
||||
import axios from '../axios'; |
||||
|
||||
/* |
||||
* 查询 |
||||
*/ |
||||
export function getList(num: number, page: number, obj:object){ |
||||
const rData = { |
||||
num:num, |
||||
page:page, |
||||
industryId:obj['industryId'], |
||||
serviceTypeId:obj['serviceTypeId'], |
||||
questionContent:obj['questionContent'] |
||||
}; |
||||
return axios({ |
||||
url: "/ex/question/list", |
||||
method: 'post', |
||||
data: rData |
||||
}) |
||||
} |
||||
|
||||
/* |
||||
* 删除(明细) |
||||
*/ |
||||
export function deleteQuestion(id: number) { |
||||
return axios({ |
||||
url: '/ex/question/delete?id=' + id, |
||||
method: 'get' |
||||
}); |
||||
} |
||||
|
||||
/* |
||||
* 删除 |
||||
*/ |
||||
export function deleteQuestionList(ids: any) { |
||||
return axios({ |
||||
url: '/ex/question/deleteList', |
||||
method: 'post', |
||||
data: ids |
||||
}); |
||||
} |
||||
|
||||
/* |
||||
* 新增题目 |
||||
*/ |
||||
export function add(questionData: object) { |
||||
return axios({ |
||||
url: "/ex/question/add", |
||||
method: 'post', |
||||
data: questionData |
||||
}); |
||||
} |
||||
|
||||
/* |
||||
* 修改题目 |
||||
*/ |
||||
export function update(questionData: object) { |
||||
return axios({ |
||||
url: "/ex/question/update", |
||||
method: 'post', |
||||
data: questionData |
||||
}); |
||||
} |
||||
|
||||
/* |
||||
* 行业 |
||||
*/ |
||||
export function findIndustry() { |
||||
return axios({ |
||||
url: '/ex/question/findIndustry', |
||||
method: 'get' |
||||
}) |
||||
} |
||||
|
||||
/* |
||||
* 题目详情 |
||||
*/ |
||||
export function getDetail(id: string|null) { |
||||
return axios({ |
||||
url: '/ex/question/getDetail?id=' + id, |
||||
method: 'get' |
||||
}); |
||||
} |
@ -0,0 +1,505 @@ |
||||
import React, { Component } from'react'; |
||||
import { Form, Input, Button, Radio, Checkbox, Select, message } from 'antd'; |
||||
import { dictionary } from "api/dict/index"; |
||||
import { add, findIndustry } from 'api/question'; |
||||
import * as XLSX from 'xlsx'; |
||||
import { saveAs } from 'file-saver'; |
||||
|
||||
const { Option } = Select; |
||||
|
||||
// 定义单个试题的状态接口
|
||||
interface QuestionState { |
||||
questionTypes: string; |
||||
industryId: string | null; |
||||
serviceTypeId: string | null; |
||||
questionContent: string; |
||||
answerOptions: { [key: string]: string }; |
||||
answer: string | null; |
||||
} |
||||
|
||||
// 定义组件的状态接口
|
||||
interface States { |
||||
industryDict: any; |
||||
serviceTypeDict: any; |
||||
isLoading: boolean; |
||||
questions: QuestionState[]; |
||||
} |
||||
|
||||
class QuestionAdd extends Component<any, States> { |
||||
formRef: any; |
||||
fileInputRef: any; |
||||
|
||||
constructor(props: any) { |
||||
super(props); |
||||
this.formRef = React.createRef(); |
||||
this.fileInputRef = React.createRef(); |
||||
this.state = { |
||||
industryDict: undefined, |
||||
serviceTypeDict: undefined, |
||||
isLoading: false, |
||||
questions: [ |
||||
{ |
||||
questionTypes: '1', |
||||
questionContent: '', |
||||
answerOptions: { A: '', B: '', C: '', D: ''}, |
||||
answer: null, |
||||
industryId: null, |
||||
serviceTypeId: null |
||||
} |
||||
] |
||||
}; |
||||
} |
||||
|
||||
// 初期
|
||||
componentDidMount() { |
||||
this.getDict(); |
||||
this.findIndustry(); |
||||
} |
||||
|
||||
// 字典
|
||||
getDict() { |
||||
// 服务类型
|
||||
dictionary('serviceTypeDict').then((res) => { |
||||
if (res.data) { |
||||
this.setState({ serviceTypeDict: res.data }); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
// 行业
|
||||
findIndustry() { |
||||
// 监管行业
|
||||
findIndustry().then((res) => { |
||||
if (res.data) { |
||||
this.setState({ industryDict: res.data }); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
// 题型
|
||||
handleQuestionTypeChange = (index: number, value: string) => { |
||||
this.setState((prevState) => { |
||||
const questions = [...prevState.questions]; |
||||
questions[index].questionTypes = value; |
||||
questions[index].answer = null; |
||||
return { |
||||
questions |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
// 单选框
|
||||
handleRadioChange = (index: number, value: string) => { |
||||
this.setState((prevState) => { |
||||
const questions = [...prevState.questions]; |
||||
questions[index].answer = value; |
||||
return { |
||||
questions |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
// 多选框
|
||||
handleCheckboxChange = (index: number, type: string, values: (string | number | boolean)[] | null) => { |
||||
this.setState((prevState) => { |
||||
const questions = [...prevState.questions]; |
||||
const currentAnswer = questions[index].answer || ''; |
||||
const currentSelectedArray = currentAnswer? currentAnswer.split(',') : []; |
||||
if (!values || values.length === 0) { |
||||
const newSelectedArray = currentSelectedArray.filter(val => val!== type); |
||||
newSelectedArray.sort(); |
||||
questions[index].answer = newSelectedArray.join(','); |
||||
} else { |
||||
const stringValues = values.map((val) => String(val)); |
||||
const newSelectedArray = Array.from(new Set([...currentSelectedArray, ...stringValues])); |
||||
newSelectedArray.sort(); |
||||
questions[index].answer = newSelectedArray.join(','); |
||||
} |
||||
return { |
||||
questions |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
// 答案
|
||||
handleAnswerOptionChange = (index: number, option: string, value: string) => { |
||||
this.setState((prevState) => { |
||||
const questions = [...prevState.questions]; |
||||
questions[index].answerOptions[option] = value; |
||||
return { |
||||
questions |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
// 新增试题
|
||||
addNewQuestion = () => { |
||||
this.setState((prevState) => ({ |
||||
questions: [ |
||||
...prevState.questions, |
||||
{ |
||||
questionTypes: '1', |
||||
questionContent: '', |
||||
answerOptions: { A: '', B: '', C: '', D: ''}, |
||||
answerDisabled: false, |
||||
answer: null, |
||||
industryId: null, |
||||
serviceTypeId: null |
||||
} |
||||
] |
||||
})); |
||||
}; |
||||
|
||||
// 删除试题
|
||||
deleteQuestion = (index: number) => { |
||||
this.setState((prevState) => { |
||||
const questions = [...prevState.questions]; |
||||
questions.splice(index, 1); |
||||
return { |
||||
questions |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
// 处理表单提交
|
||||
handleSubmit = () => { |
||||
this.setState({ isLoading: true }); |
||||
this.formRef.current.validateFields().then((values: Record<string, any>) => { |
||||
const questions = this.state.questions.map((question, index) => { |
||||
const industryId = values[`industryId_${index}`]; |
||||
const serviceTypeId = values[`serviceTypeId_${index}`]; |
||||
const questionContent = values[`questionContent_${index}`]; |
||||
return { |
||||
...question, |
||||
industryId, |
||||
serviceTypeId, |
||||
questionContent |
||||
}; |
||||
}); |
||||
|
||||
add(questions).then((res) => { |
||||
const count = res.data; |
||||
if (count>0) { |
||||
message.success(`成功新增 ${count} 条试题`); |
||||
this.setState({ isLoading: false }); |
||||
this.props.history.push('/questionList'); |
||||
} else { |
||||
message.error('新增试题失败,请稍后重试'); |
||||
this.setState({ isLoading: false }); |
||||
} |
||||
}).catch(() => { |
||||
message.error('新增试题时发生错误,请检查'); |
||||
this.setState({ isLoading: false }); |
||||
}); |
||||
}).catch(() => { |
||||
this.setState({ isLoading: false }); |
||||
}); |
||||
}; |
||||
|
||||
// 下载模板
|
||||
downloadTemplate = () => { |
||||
const headers = ['题型', '监管行业', 'AQ服务类型', '题干', '选项A', '选项B', '选项C', '选项D', '答案']; |
||||
const ws = XLSX.utils.aoa_to_sheet([headers]); |
||||
const wb = XLSX.utils.book_new(); |
||||
XLSX.utils.book_append_sheet(wb, ws, '试题模板'); |
||||
const wbOut = XLSX.write(wb, { bookType: 'xlsx', type: 'array' }); |
||||
saveAs(new Blob([wbOut], { type: 'application/octet-stream' }), '试题模板.xlsx'); |
||||
}; |
||||
|
||||
// 一键导入
|
||||
handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { |
||||
const file = e.target.files?.[0]; |
||||
if (file) { |
||||
const reader = new FileReader(); |
||||
reader.onload = (event) => { |
||||
const data = new Uint8Array(event.target?.result as ArrayBuffer); |
||||
const workbook = XLSX.read(data, { type: 'array' }); |
||||
const firstSheetName = workbook.SheetNames[0]; |
||||
const worksheet = workbook.Sheets[firstSheetName]; |
||||
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); |
||||
const rows = jsonData.slice(1); |
||||
const newQuestions = rows.map((row: any) => { |
||||
const question: QuestionState = { |
||||
questionTypes: String(row[0]), |
||||
industryId: String(row[1]), |
||||
serviceTypeId: String(row[2]).trim().toLowerCase(), |
||||
questionContent: String(row[3]), |
||||
answerOptions: { |
||||
A: String(row[4]), |
||||
B: String(row[5]), |
||||
C: String(row[6]), |
||||
D: String(row[7]) |
||||
}, |
||||
answer: String(row[8]) |
||||
}; |
||||
return question; |
||||
}); |
||||
this.setState({ questions: newQuestions }, () => { |
||||
const formValues = {}; |
||||
newQuestions.forEach((question, index) => { |
||||
formValues[`questionContent_${index}`] = question.questionContent; |
||||
formValues[`industryId_${index}`] = question.industryId; |
||||
formValues[`serviceTypeId_${index}`] = question.serviceTypeId; |
||||
formValues[`answer_${index}`] = question.answer; |
||||
formValues[`answerOption_A_${index}`] = question.answerOptions.A; |
||||
formValues[`answerOption_B_${index}`] = question.answerOptions.B; |
||||
formValues[`answerOption_C_${index}`] = question.answerOptions.C; |
||||
formValues[`answerOption_D_${index}`] = question.answerOptions.D; |
||||
}); |
||||
this.formRef.current.setFieldsValue(formValues); |
||||
}); |
||||
}; |
||||
reader.readAsArrayBuffer(file); |
||||
} |
||||
}; |
||||
|
||||
// 文件
|
||||
handleImportClick = () => { |
||||
this.fileInputRef.current?.click(); |
||||
}; |
||||
|
||||
render() { |
||||
const { industryDict, serviceTypeDict, questions, isLoading } = this.state; |
||||
// 使用 this.props.history 进行页面跳转
|
||||
const handleListQuestion = () => { |
||||
this.props.history.push('/questionList'); |
||||
}; |
||||
return ( |
||||
<div className="container"> |
||||
<div style={{ textAlign: 'right'}}> |
||||
<Button type="default" style={{ marginRight: 10 }} onClick={this.downloadTemplate}>下载模版</Button> |
||||
<Button type="default" onClick={this.handleImportClick}>一键导入</Button> |
||||
<input |
||||
type="file" |
||||
ref={this.fileInputRef} |
||||
style={{ display: 'none' }} |
||||
accept=".xlsx,.xls" |
||||
onChange={this.handleFileChange} |
||||
/> |
||||
</div> |
||||
<Form |
||||
ref={this.formRef} |
||||
layout="inline" |
||||
className="ant-bg-light" |
||||
> |
||||
{questions.map((question, index) => ( |
||||
<div key={index} style={{ marginBottom: 30 }}> |
||||
<div style={{ display: 'flex' }}> |
||||
<Form.Item> |
||||
<Radio.Group |
||||
value={question.questionTypes} |
||||
onChange={(e) => this.handleQuestionTypeChange(index, e.target.value)}> |
||||
<Radio.Button value="1">单选题</Radio.Button> |
||||
<Radio.Button value="2">多选题</Radio.Button> |
||||
</Radio.Group> |
||||
</Form.Item> |
||||
<Form.Item |
||||
label="监管行业:" |
||||
name={`industryId_${index}`} |
||||
> |
||||
<Select placeholder="请选择监管行业" |
||||
style={{ width: 240 }} |
||||
allowClear |
||||
value={question.industryId}> |
||||
{ |
||||
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="AQ服务类型:" |
||||
name={`serviceTypeId_${index}`} |
||||
> |
||||
<Select placeholder="请选择AQ服务类型" |
||||
style={{ width: 240 }} |
||||
allowClear |
||||
value={question.serviceTypeId}> |
||||
{ |
||||
serviceTypeDict && serviceTypeDict.length > 0? |
||||
(() => { |
||||
let rows = []; |
||||
for (let i = 0; i < serviceTypeDict.length; i++) { |
||||
const item = serviceTypeDict[i]; |
||||
rows.push( |
||||
<Option value={String(item.dictKey).trim().toLowerCase()}>{item.dictValue}</Option> |
||||
); |
||||
} |
||||
return rows; |
||||
})() |
||||
: |
||||
<Option disabled>暂无数据</Option> |
||||
} |
||||
</Select> |
||||
</Form.Item> |
||||
<Form.Item> |
||||
{index > 0 && (<Button type="link" onClick={() => this.deleteQuestion(index)}>X</Button>)} |
||||
</Form.Item> |
||||
</div> |
||||
<Form.Item |
||||
label="题干:" |
||||
name={`questionContent_${index}`} |
||||
style={{marginTop: 10 }} |
||||
> |
||||
<Input.TextArea |
||||
placeholder="请输入题干内容" |
||||
value={question.questionContent} |
||||
style={{ width: 1100, height: 60 }} |
||||
/> |
||||
</Form.Item> |
||||
<Form.Item style={{marginTop: 10, marginLeft: 40}}> |
||||
<div> |
||||
<div style={{ display: 'flex' }}> |
||||
{question.questionTypes === '1'? ( |
||||
<Radio.Group |
||||
value={question.answer} |
||||
onChange={(e) => this.handleRadioChange(index, e.target.value)} |
||||
> |
||||
<Radio value="A">A</Radio> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.A} |
||||
style={{ width: 490}} |
||||
onChange={(e) => this.handleAnswerOptionChange(index, 'A', e.target.value)} |
||||
/> |
||||
</Radio.Group> |
||||
) : ( |
||||
<Checkbox.Group |
||||
value={question.answer? String(question.answer || '').split(',') : []} |
||||
onChange={(values) => this.handleCheckboxChange(index,'A', values,)}> |
||||
<Checkbox value="A">A</Checkbox> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.A} |
||||
style={{ width: 500}} |
||||
onChange={(e) => this.handleAnswerOptionChange(index, 'A', e.target.value)} |
||||
/> |
||||
</Checkbox.Group> |
||||
)} |
||||
{question.questionTypes === '1'? ( |
||||
<Radio.Group |
||||
value={question.answer} |
||||
onChange={(e) => this.handleRadioChange(index, e.target.value)} |
||||
style={{ marginLeft: 20 }} |
||||
> |
||||
<Radio value="B">B</Radio> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.B} |
||||
style={{ width: 490}} |
||||
onChange={(e) => this.handleAnswerOptionChange(index, 'B', e.target.value)} |
||||
/> |
||||
</Radio.Group> |
||||
) : ( |
||||
<Checkbox.Group |
||||
style={{ marginLeft: 20 }} |
||||
value={question.answer? String(question.answer || '').split(',') : []} |
||||
onChange={(values) => this.handleCheckboxChange(index,'B',values)}> |
||||
<Checkbox value="B">B</Checkbox> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.B} |
||||
style={{ width: 500}} |
||||
onChange={(e) => this.handleAnswerOptionChange(index, 'B', e.target.value)} |
||||
/> |
||||
</Checkbox.Group> |
||||
)} |
||||
</div> |
||||
<div style={{ display: 'flex', marginTop: 10 }}> |
||||
{question.questionTypes === '1'? ( |
||||
<Radio.Group |
||||
value={question.answer} |
||||
onChange={(e) => this.handleRadioChange(index, e.target.value)} |
||||
> |
||||
<Radio value="C">C</Radio> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.C} |
||||
style={{ width: 490}} |
||||
onChange={(e) => this.handleAnswerOptionChange(index, 'C', e.target.value)} |
||||
/> |
||||
</Radio.Group> |
||||
) : ( |
||||
<Checkbox.Group |
||||
value={question.answer? String(question.answer || '').split(',') : []} |
||||
onChange={(values) => this.handleCheckboxChange(index,'C', values)}> |
||||
<Checkbox value="C">C</Checkbox> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.C} |
||||
style={{ width: 500}} |
||||
onChange={(e) => this.handleAnswerOptionChange(index, 'C', e.target.value)} |
||||
/> |
||||
</Checkbox.Group> |
||||
)} |
||||
{question.questionTypes === '1'? ( |
||||
<Radio.Group |
||||
value={question.answer} |
||||
onChange={(e) => this.handleRadioChange(index, e.target.value)} |
||||
style={{ marginLeft: 20 }} |
||||
> |
||||
<Radio value="D">D</Radio> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.D} |
||||
style={{ width: 490}} |
||||
onChange={(e) => this.handleAnswerOptionChange(index, 'D', e.target.value)} |
||||
/> |
||||
</Radio.Group> |
||||
) : ( |
||||
<Checkbox.Group |
||||
style={{ marginLeft: 20 }} |
||||
value={question.answer? String(question.answer || '').split(',') : []} |
||||
onChange={(values) => this.handleCheckboxChange(index,'D',values)}> |
||||
<Checkbox value="D">D</Checkbox> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.D} |
||||
style={{ width: 500}} |
||||
onChange={(e) => this.handleAnswerOptionChange(index, 'D', e.target.value)} |
||||
/> |
||||
</Checkbox.Group> |
||||
)} |
||||
</div> |
||||
</div> |
||||
</Form.Item> |
||||
</div> |
||||
))} |
||||
</Form> |
||||
<div style={{ textAlign: 'right'}}> |
||||
<Button type="default" onClick={this.addNewQuestion}> |
||||
新增试题 |
||||
</Button> |
||||
</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" loading={isLoading} onClick={this.handleSubmit}> |
||||
确定添加 |
||||
</Button> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
} |
||||
export default QuestionAdd; |
@ -0,0 +1,393 @@ |
||||
import React, { Component } from'react'; |
||||
import {Form, Input, Button, Table, Select, message, Modal} from 'antd'; |
||||
import { TableRowSelection } from 'antd/lib/table/interface'; |
||||
import {deleteQuestion, deleteQuestionList, findIndustry, getList} from 'api/question'; |
||||
import { dictionary } from "api/dict/index"; |
||||
|
||||
const { Option } = Select; |
||||
|
||||
interface States { |
||||
num: number; |
||||
page: number; |
||||
listQuery: { |
||||
industryId: string | undefined; |
||||
serviceTypeId: string | undefined; |
||||
questionContent: string | undefined; |
||||
}; |
||||
list: any[]; |
||||
total: number; |
||||
loading: boolean; |
||||
currentRow: object; |
||||
title: string; |
||||
modalText: string; |
||||
modalWidth: number | string; |
||||
industryDict: any; |
||||
serviceTypeDict: any; |
||||
selectedRowKeys: number[]; |
||||
isAllSelected: boolean; |
||||
} |
||||
|
||||
class QuestionList extends Component<any, States> { |
||||
formRef: any; |
||||
constructor(props: any) { |
||||
super(props); |
||||
this.formRef = React.createRef(); |
||||
this.state = { |
||||
num: 10, |
||||
page: 1, |
||||
listQuery: { |
||||
industryId: undefined, |
||||
serviceTypeId: undefined, |
||||
questionContent: undefined |
||||
}, |
||||
list: [], |
||||
total: 0, |
||||
loading: false, |
||||
currentRow: { |
||||
id: 0, |
||||
status: 0 |
||||
}, |
||||
title: '', |
||||
modalText: '', |
||||
modalWidth: 0, |
||||
industryDict: undefined, |
||||
serviceTypeDict: undefined, |
||||
selectedRowKeys: [], |
||||
isAllSelected: false, |
||||
}; |
||||
} |
||||
|
||||
componentDidMount() { |
||||
this.findDict(); |
||||
this.findIndustry(); |
||||
this.getList(); |
||||
} |
||||
|
||||
// 监管行业
|
||||
findIndustry() { |
||||
findIndustry().then((res: any) => { |
||||
if (res.data) { |
||||
this.setState({ industryDict: res.data }); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
// AQ服务类型
|
||||
findDict() { |
||||
dictionary('serviceTypeDict').then((res) => { |
||||
if (res.data) { |
||||
this.setState({ serviceTypeDict: res.data }); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
// 查询
|
||||
getList() { |
||||
this.setState({ loading: true }); |
||||
const { num, page, listQuery } = this.state; |
||||
getList(num, page, listQuery).then((res) => { |
||||
this.setState({ |
||||
loading: false, |
||||
list: res.data.data, |
||||
total: res.data.total, |
||||
selectedRowKeys: [], |
||||
isAllSelected: false, |
||||
}); |
||||
this.setState({ loading: false }); |
||||
}).catch(() => { |
||||
this.setState({ loading: false }); |
||||
}); |
||||
} |
||||
|
||||
// 重置
|
||||
handleReset = () => { |
||||
if (this.formRef.current) { |
||||
// 重置表单字段
|
||||
this.formRef.current.resetFields(); |
||||
// 重置 listQuery 状态
|
||||
this.setState({ |
||||
listQuery: { |
||||
industryId: undefined, |
||||
serviceTypeId: undefined, |
||||
questionContent: undefined |
||||
}, |
||||
selectedRowKeys: [], |
||||
isAllSelected: false, |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
// 删除(明细)
|
||||
deleteSingle = (id: number) => { |
||||
Modal.confirm({ |
||||
title: '确认删除', |
||||
content: '你确定要删除这个问题吗?', |
||||
onOk: () => { |
||||
deleteQuestion(id).then((res) => { |
||||
const isSuccess = res.data; |
||||
if (isSuccess) { |
||||
message.success('删除成功'); |
||||
this.getList(); |
||||
} else { |
||||
message.error('删除失败,请稍后重试'); |
||||
} |
||||
}).catch(() => { |
||||
message.error('删除时发生错误,请检查'); |
||||
}); |
||||
}, |
||||
onCancel: () => { |
||||
}, |
||||
}); |
||||
}; |
||||
|
||||
// 删除
|
||||
deleteMultiple = () => { |
||||
const { selectedRowKeys } = this.state; |
||||
if (selectedRowKeys.length === 0) { |
||||
message.warning('请选择要删除的问题'); |
||||
return; |
||||
} |
||||
Modal.confirm({ |
||||
title: '确认删除', |
||||
content: '你确定要删除这些选中的问题吗?', |
||||
onOk: () => { |
||||
deleteQuestionList(selectedRowKeys) |
||||
.then((res) => { |
||||
const isSuccess = res.data; |
||||
if (isSuccess) { |
||||
message.success('删除成功'); |
||||
this.getList(); |
||||
} else { |
||||
message.error('删除失败,请稍后重试'); |
||||
} |
||||
}) |
||||
.catch(() => { |
||||
message.error('删除时发生错误,请检查'); |
||||
}); |
||||
}, |
||||
onCancel: () => { |
||||
}, |
||||
}); |
||||
}; |
||||
|
||||
// 多选
|
||||
onSelectChange = (selectedRowKeys: React.Key[]) => { |
||||
this.setState({ |
||||
selectedRowKeys: selectedRowKeys as number[], |
||||
isAllSelected: selectedRowKeys.length === this.state.list.length |
||||
}); |
||||
}; |
||||
|
||||
// 单选
|
||||
onSelect = (record: any, selected: boolean) => { |
||||
if (selected) { |
||||
// 单选时只保留当前选中行
|
||||
this.setState({ |
||||
selectedRowKeys: [record.id], |
||||
isAllSelected: false |
||||
}); |
||||
} else { |
||||
// 取消选中时清空选中行
|
||||
this.setState({ |
||||
selectedRowKeys: [], |
||||
isAllSelected: false |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
render() { |
||||
const onFinish = (values: object) => { |
||||
const _listQuery = { ...this.state.listQuery, ...values }; |
||||
this.setState({ listQuery: _listQuery }); |
||||
this.getList(); |
||||
}; |
||||
|
||||
const { industryDict, serviceTypeDict, selectedRowKeys } = this.state; |
||||
|
||||
// 行选择
|
||||
const rowSelection: TableRowSelection<any> = { |
||||
selectedRowKeys, |
||||
onChange: this.onSelectChange, |
||||
onSelect: this.onSelect, |
||||
getCheckboxProps: (record) => ({ |
||||
checked: selectedRowKeys.includes(record.id), |
||||
indeterminate: selectedRowKeys.includes(record.id), |
||||
}) |
||||
}; |
||||
|
||||
// 页面跳转
|
||||
const handleAddQuestion = () => { |
||||
this.props.history.push('/questionAdd'); |
||||
}; |
||||
|
||||
const columns: any = [ |
||||
{ title: '序号', dataIndex: 'index', key: 'index', align: 'center', width: 60, |
||||
render: (_: number, __: number, index: number) => { |
||||
const { page, num } = this.state; |
||||
return (page - 1) * num + index + 1; |
||||
} |
||||
}, |
||||
{ title: '监管行业', dataIndex: 'industryId', key: 'industryId', align: 'center', width: 150, |
||||
render: (industryId:any) => { |
||||
const industry = industryDict?.find((item: { industryId: string | number; industryName: string }) => String(item.industryId) === String(industryId)); |
||||
return industry? industry.industryName : industryId; |
||||
} |
||||
}, |
||||
{ 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) === String(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: '题目ID', dataIndex: 'id', key: 'id', width: 120}, |
||||
{ title: '操作', key: 'operation', align: 'center', fixed: 'right', width: 120, |
||||
render: (record: any) => [ |
||||
<span className='mr10 link' onClick={() => { |
||||
this.setState({title: '删除', modalWidth: '85%'}) |
||||
this.deleteSingle(record.id); |
||||
}}>删除</span>, |
||||
<span className="mr10 link" onClick={() => { |
||||
this.setState({title: '修正', modalWidth: '85%'}) |
||||
sessionStorage.setItem('id', String(record.id)); |
||||
this.props.history.push(`/questionUp`); |
||||
}}>修正</span> |
||||
] |
||||
}, |
||||
]; |
||||
|
||||
// 分页切换
|
||||
const changePage = (current: number, pageSize?: number) => { |
||||
setTimeout(() => { |
||||
this.setState({page: current, num: pageSize || 20}); |
||||
this.getList(); |
||||
}, 0); |
||||
}; |
||||
|
||||
// 多少每页
|
||||
const selectChange = (page: number, num: number) => { |
||||
this.setState({ page, num }); |
||||
this.getList(); |
||||
}; |
||||
|
||||
const { list, loading } = this.state; |
||||
|
||||
return ( |
||||
<div className="container"> |
||||
<div className="list-filter"> |
||||
<Form |
||||
ref={this.formRef} |
||||
className="filter" |
||||
layout="inline" |
||||
name="basic" |
||||
onFinish={onFinish} |
||||
> |
||||
<Form.Item |
||||
label="监管行业:" |
||||
name="industryId" |
||||
> |
||||
<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="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: 240 }}/> |
||||
</Form.Item> |
||||
<Form.Item> |
||||
<Button type="default" onClick={this.handleReset}>重置</Button> |
||||
</Form.Item> |
||||
<Form.Item> |
||||
<Button type="primary" htmlType="submit">查询</Button> |
||||
</Form.Item> |
||||
</Form> |
||||
</div> |
||||
<Form |
||||
className="filter" |
||||
layout="inline" |
||||
name="basic" |
||||
onFinish={onFinish} |
||||
style={{ display: 'flex', justifyContent: 'flex-end' }} |
||||
> |
||||
<Form.Item> |
||||
<Button type="default" onClick={this.deleteMultiple}>删除</Button> |
||||
</Form.Item> |
||||
<Form.Item> |
||||
<Button type="primary" onClick={handleAddQuestion}>新增试题</Button> |
||||
</Form.Item> |
||||
</Form> |
||||
<Table |
||||
dataSource={list} |
||||
columns={columns} |
||||
rowKey="id" |
||||
loading={loading} |
||||
scroll={{ y: '400px' }} |
||||
pagination={{ |
||||
total: this.state.total, |
||||
current: this.state.page, |
||||
showQuickJumper: true, |
||||
showSizeChanger: true, |
||||
showTotal: (total) => `共 ${total} 条`, |
||||
onShowSizeChange: selectChange, |
||||
onChange: changePage |
||||
}} |
||||
rowSelection={rowSelection} |
||||
/> |
||||
</div> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export default QuestionList; |
@ -0,0 +1,403 @@ |
||||
import React, { Component } from'react'; |
||||
import { Form, Input, Button, Radio, Checkbox, Select, message } from 'antd'; |
||||
import { dictionary } from "api/dict/index"; |
||||
import {findIndustry, getDetail, update} from 'api/question'; |
||||
|
||||
const { Option } = Select; |
||||
|
||||
interface QuestionState { |
||||
id: string|null; |
||||
questionTypes: string; |
||||
industryId: string; |
||||
serviceTypeId: string; |
||||
questionContent: string; |
||||
answerOptions: {[ |
||||
key: string]: string |
||||
}; |
||||
answer: string; |
||||
} |
||||
|
||||
interface States { |
||||
industryDict: any; |
||||
serviceTypeDict: any; |
||||
isLoading: boolean; |
||||
question: QuestionState; |
||||
} |
||||
|
||||
class QuestionUp extends Component<any, States> { |
||||
formRef: any; |
||||
constructor(props: any) { |
||||
super(props); |
||||
this.formRef = React.createRef(); |
||||
this.state = { |
||||
industryDict: undefined, |
||||
serviceTypeDict: undefined, |
||||
isLoading: false, |
||||
question: { |
||||
id: '', |
||||
questionTypes: '1', |
||||
industryId: '', |
||||
serviceTypeId: '', |
||||
questionContent: '', |
||||
answerOptions: { A: '', B: '', C: '', D: '' }, |
||||
answer: '' |
||||
}, |
||||
}; |
||||
} |
||||
|
||||
componentDidMount() { |
||||
this.findIndustry() |
||||
this.findDict(); |
||||
this.getDetail(); |
||||
} |
||||
|
||||
// 监管行业
|
||||
findIndustry() { |
||||
findIndustry().then((res: any) => { |
||||
if (res.data) { |
||||
this.setState({ industryDict: res.data }); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
// AQ服务类型
|
||||
findDict() { |
||||
dictionary('serviceTypeDict').then((res) => { |
||||
if (res.data) { |
||||
this.setState({ serviceTypeDict: res.data }); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
// 题目详情
|
||||
getDetail = () => { |
||||
const id = sessionStorage.getItem('id'); |
||||
sessionStorage.removeItem('id'); |
||||
getDetail(id).then((res: any) => { |
||||
if (res.data) { |
||||
let answerOptions = {}; |
||||
const options = res.data.options.split(';'); |
||||
options.forEach((option: any) => { |
||||
const [key, value] = option.split(':'); |
||||
answerOptions[key] = value; |
||||
}); |
||||
const question: QuestionState = { |
||||
id:id, |
||||
questionTypes: String(res.data.questionTypes), |
||||
industryId: String(res.data.industryId), |
||||
serviceTypeId: String(res.data.serviceTypeId), |
||||
questionContent: String(res.data.questionContent), |
||||
answerOptions: answerOptions, |
||||
answer: res.data.answer |
||||
}; |
||||
this.setState({ question: question }, () => { |
||||
const formValues = {}; |
||||
formValues['questionTypes'] = question.questionTypes; |
||||
formValues['industryId'] = question.industryId; |
||||
formValues['serviceTypeId'] = question.serviceTypeId; |
||||
formValues['questionContent'] = question.questionContent; |
||||
formValues['answer'] = question.answer; |
||||
formValues['answerOption_A'] = question.answerOptions.A; |
||||
formValues['answerOption_B'] = question.answerOptions.B; |
||||
formValues['answerOption_C'] = question.answerOptions.C; |
||||
formValues['answerOption_D'] = question.answerOptions.D; |
||||
this.formRef.current.setFieldsValue(formValues); |
||||
}); |
||||
} |
||||
}).catch(() => { |
||||
message.error('获取题目详情失败,请重试'); |
||||
}); |
||||
}; |
||||
|
||||
// 题型
|
||||
handleQuestionTypeChange = (value: string) => { |
||||
this.setState((prevState) => { |
||||
prevState.question.questionTypes = value; |
||||
prevState.question.answer = ''; |
||||
return { |
||||
question: prevState.question |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
// 单选框
|
||||
handleRadioChange = (value: string) => { |
||||
this.setState((prevState) => { |
||||
prevState.question.answer = value; |
||||
return { |
||||
question: prevState.question |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
// 多选框
|
||||
handleCheckboxChange = (type: string, values: (string | number | boolean)[] | null) => { |
||||
const currentAnswer = this.state.question.answer; |
||||
const currentSelectedArray = currentAnswer? currentAnswer.split(',') : []; |
||||
if (!values || values.length === 0) { |
||||
const newSelectedArray = currentSelectedArray.filter(val => val!== type); |
||||
newSelectedArray.sort(); |
||||
this.setState((prevState) => { |
||||
prevState.question.answer = newSelectedArray.join(','); |
||||
return { |
||||
question: prevState.question |
||||
}; |
||||
}); |
||||
} else { |
||||
const stringValues = values.map((val) => String(val)); |
||||
const newSelectedArray = Array.from(new Set([...currentSelectedArray, ...stringValues])); |
||||
newSelectedArray.sort(); |
||||
this.setState((prevState) => { |
||||
prevState.question.answer = newSelectedArray.join(','); |
||||
return { |
||||
question: prevState.question |
||||
}; |
||||
}); |
||||
} |
||||
}; |
||||
|
||||
// 答案
|
||||
handleAnswerOptionChange = (option: string, value: string) => { |
||||
this.setState((prevState) => { |
||||
prevState.question.answerOptions[option] = value; |
||||
return { |
||||
question: prevState.question |
||||
}; |
||||
}); |
||||
}; |
||||
|
||||
// 保存修改
|
||||
update = () => { |
||||
this.setState({ isLoading: true }); |
||||
this.formRef.current.validateFields().then((values: Record<string, any>) => { |
||||
const { question } = this.state; |
||||
const updatedQuestion = { |
||||
...question, |
||||
industryId: values['industryId'], |
||||
serviceTypeId: values['serviceTypeId'], |
||||
questionContent: values['questionContent'] |
||||
}; |
||||
this.setState({ question: updatedQuestion }); |
||||
update(updatedQuestion).then((res) => { |
||||
const isSuccess = res.data; |
||||
if (isSuccess) { |
||||
message.success('修改成功'); |
||||
this.setState({ isLoading: false }); |
||||
this.props.history.push('/questionList'); |
||||
} else { |
||||
message.error('修改失败,请稍后重试'); |
||||
this.setState({ isLoading: false }); |
||||
} |
||||
}).catch(() => { |
||||
message.error('修改时发生错误,请检查'); |
||||
this.setState({ isLoading: false }); |
||||
}); |
||||
}); |
||||
}; |
||||
render() { |
||||
const { industryDict, serviceTypeDict, question, isLoading } = this.state; |
||||
const handleListQuestion = () => { |
||||
this.props.history.push('/questionList'); |
||||
}; |
||||
return ( |
||||
<div className="container"> |
||||
<Form ref={this.formRef} layout="inline"> |
||||
<div style={{ display: 'flex'}}> |
||||
<Form.Item name="questionTypes"> |
||||
<Radio.Group |
||||
onChange={(e) => this.handleQuestionTypeChange(e.target.value)}> |
||||
<Radio.Button value="1">单选题</Radio.Button> |
||||
<Radio.Button value="2">多选题</Radio.Button> |
||||
</Radio.Group> |
||||
</Form.Item> |
||||
<Form.Item |
||||
label="监管行业:" |
||||
name="industryId" |
||||
> |
||||
<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="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={String(item.dictKey).trim().toLowerCase()}>{item.dictValue}</Option> |
||||
); |
||||
} |
||||
return rows; |
||||
})() |
||||
: |
||||
<Option disabled>暂无数据</Option> |
||||
} |
||||
</Select> |
||||
</Form.Item> |
||||
</div> |
||||
<Form.Item |
||||
label="题干:" |
||||
name="questionContent" |
||||
style={{ marginTop: 10 }} |
||||
> |
||||
<Input.TextArea |
||||
placeholder="请输入题干内容" |
||||
style={{ width: 1100, height: 60 }} |
||||
/> |
||||
</Form.Item> |
||||
<Form.Item style={{ marginTop: 10, marginLeft: 40 }}> |
||||
<div> |
||||
<div style={{ display: 'flex' }}> |
||||
{question.questionTypes === '1'? ( |
||||
<Radio.Group |
||||
value={question.answer} |
||||
onChange={(e) => this.handleRadioChange(e.target.value)} |
||||
> |
||||
<Radio value="A">A</Radio> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.A} |
||||
style={{ width: 490}} |
||||
onChange={(e) => this.handleAnswerOptionChange('A', e.target.value)} |
||||
/> |
||||
</Radio.Group> |
||||
) : ( |
||||
<Checkbox.Group |
||||
value={question.answer? String(question.answer || '').split(',') : []} |
||||
onChange={(values) => this.handleCheckboxChange('A', values,)}> |
||||
<Checkbox value="A">A</Checkbox> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.A} |
||||
style={{ width: 500}} |
||||
onChange={(e) => this.handleAnswerOptionChange('A', e.target.value)} |
||||
/> |
||||
</Checkbox.Group> |
||||
)} |
||||
{question.questionTypes === '1' ? ( |
||||
<Radio.Group |
||||
value={question.answer} |
||||
onChange={(e) => this.handleRadioChange( e.target.value)} |
||||
style={{ marginLeft: 20 }} |
||||
> |
||||
<Radio value="B">B</Radio> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.B} |
||||
style={{ width: 490}} |
||||
onChange={(e) => this.handleAnswerOptionChange('B', e.target.value)} |
||||
/> |
||||
</Radio.Group> |
||||
) : ( |
||||
<Checkbox.Group |
||||
style={{ marginLeft: 20 }} |
||||
value={question.answer? String(question.answer || '').split(',') : []} |
||||
onChange={(values) => this.handleCheckboxChange('B',values)}> |
||||
<Checkbox value="B">B</Checkbox> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.B} |
||||
style={{ width: 500}} |
||||
onChange={(e) => this.handleAnswerOptionChange( 'B', e.target.value)} |
||||
/> |
||||
</Checkbox.Group> |
||||
)} |
||||
</div> |
||||
<div style={{ display: 'flex', marginTop: 10 }}> |
||||
{question.questionTypes === '1'? ( |
||||
<Radio.Group |
||||
value={question.answer} |
||||
onChange={(e) => this.handleRadioChange( e.target.value)} |
||||
> |
||||
<Radio value="C">C</Radio> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.C} |
||||
style={{ width: 490}} |
||||
onChange={(e) => this.handleAnswerOptionChange('C', e.target.value)} |
||||
/> |
||||
</Radio.Group> |
||||
) : ( |
||||
<Checkbox.Group |
||||
value={question.answer? String(question.answer || '').split(',') : []} |
||||
onChange={(values) => this.handleCheckboxChange('C', values)}> |
||||
<Checkbox value="C">C</Checkbox> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.C} |
||||
style={{ width: 500}} |
||||
onChange={(e) => this.handleAnswerOptionChange( 'C', e.target.value)} |
||||
/> |
||||
</Checkbox.Group> |
||||
)} |
||||
{question.questionTypes === '1'? ( |
||||
<Radio.Group |
||||
value={question.answer} |
||||
onChange={(e) => this.handleRadioChange( e.target.value)} |
||||
style={{ marginLeft: 20 }} |
||||
> |
||||
<Radio value="D">D</Radio> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.D} |
||||
style={{ width: 490}} |
||||
onChange={(e) => this.handleAnswerOptionChange('D', e.target.value)} |
||||
/> |
||||
</Radio.Group> |
||||
) : ( |
||||
<Checkbox.Group |
||||
style={{ marginLeft: 20 }} |
||||
value={question.answer? String(question.answer || '').split(',') : []} |
||||
onChange={(values) => this.handleCheckboxChange('D',values)}> |
||||
<Checkbox value="D">D</Checkbox> |
||||
<Input |
||||
placeholder="请输入答案" |
||||
value={question.answerOptions.D} |
||||
style={{ width: 500}} |
||||
onChange={(e) => this.handleAnswerOptionChange('D', e.target.value)} |
||||
/> |
||||
</Checkbox.Group> |
||||
)} |
||||
</div> |
||||
</div> |
||||
</Form.Item> |
||||
</Form> |
||||
<div style={{ textAlign: 'right', marginTop: 30 }}> |
||||
<Button type="default" onClick={handleListQuestion} style={{ marginRight: 10 }}> |
||||
取消 |
||||
</Button> |
||||
<Button type="primary" htmlType="submit" loading={isLoading} onClick={this.update}> |
||||
保存修改 |
||||
</Button> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export default QuestionUp; |
Loading…
Reference in new issue