import React, { useEffect, useRef, useState } from 'react'; import { history, useParams, useRequest } from 'umi'; import type { ProFormInstance } from '@ant-design/pro-form'; import { ModalForm } from '@ant-design/pro-form'; import { ProFormRadio } from '@ant-design/pro-form'; import ProForm, {StepsForm, ProFormText, ProFormDatePicker, ProFormSelect, ProFormTextArea, ProFormCheckbox, ProFormDateRangePicker,} from '@ant-design/pro-form'; import ProCard from '@ant-design/pro-card'; import { Button, Checkbox, Col, Divider, Dropdown, Form, Input, List, Menu, message, Modal, Radio, Row, Space, Table, Typography, Upload, Empty, Tooltip, Popconfirm } from 'antd'; import { PageContainer } from '@ant-design/pro-layout'; import ProDescriptions from '@ant-design/pro-descriptions'; import styles from './index.less' import { saveRules, querySubjectList, queryRulesView, queryTempQuestionList, saveQuestionTypeScore, queryRulesPaper, updateScore, delTempQuestion, exchangeSortNum } from '../../service'; import { queryCourseView } from '@/pages/course/option/service'; import { queryQuestionList, queryQuestionById, queryQuestionType } from '@/pages/questionbank/service'; import { PlusOutlined, DownOutlined, DeleteOutlined, DownloadOutlined, UploadOutlined, EyeInvisibleOutlined, EyeOutlined, EditOutlined, ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons'; import ProList from '@ant-design/pro-list'; import { autoPaper, manualPaper, updatePaper } from '../service'; import ProTable, { EditableProTable } from '@ant-design/pro-table'; import QuestionSelector from '../../components/QuestionSelector'; import ScoreSetter from '../../components/ScoreSetter'; import AutoSelector from '../components/AutoSelector'; import { ConsoleMessage } from 'puppeteer-core'; import { getSubjectInfo } from '@/pages/course/subject/service'; import { forEach } from 'lodash'; /** * 保存选题 * * @param values */ const handleAppend = async (rules_id: number, rows: any[], paper_uuid: number) => { const hide = message.loading('正在添加'); try { const questions: { question_id: any; }[] = []; rows?.forEach((key) => { questions.push({ question_id: key }) }) const values = { question_count: questions?.length || 0, questions: JSON.stringify(questions), rules_id: Number(rules_id) } const _data = await manualPaper(paper_uuid ? {...values, paper_uuid: paper_uuid} : values); hide(); message.success('添加成功'); return _data; } catch (error) { hide(); message.error('添加失败请重试!'); return false; } }; /** * 保存选题试卷 * * @param values */ const handleUpdatePaper = async (rules_id: number, paper_uuid: number, paper_id: number) => { const hide = message.loading('正在保存'); try { const _data = { rules_id: Number(rules_id), paper_uuid: paper_uuid, paper_id: paper_id } if (paper_id === 0) { delete _data.paper_id; } await updatePaper(_data); hide(); message.success('保存成功'); return true; } catch (error) { hide(); message.error('保存失败请重试!'); return false; } }; /** * 删除临时表试题(接口不支持批量) * 参数为记录数组 * @param ids */ const handleRemoveTempQuestion = async (paper_uuid: number, question_ids: [{question_id: number}]) => { const hide = message.loading('正在删除'); console.log('uuidPaper', paper_uuid) if (!question_ids || !paper_uuid) return true; try { const {code, msg} = await delTempQuestion({ paper_uuid: paper_uuid, question_ids: JSON.stringify(question_ids) }); hide(); if(code === 2000 ){ message.success('删除成功,即将刷新'); }else{ message.warning(msg); } return true; } catch (error) { hide(); message.error('删除失败,请重试'); return false; } }; /** * 组卷交换临时表试题顺序 * @param paper_uuid * @param question_ids * @param rules_id * @returns bool */ const handleExchangeSortNum = async (paper_uuid: number, question_ids: string, rules_id: number) => { const hide = message.loading('正在保存修改'); try { const data = { rules_id: Number(rules_id), paper_uuid: paper_uuid, question_ids: question_ids } const success = await exchangeSortNum(data); hide(); if(success){ message.success('修改成功'); } return true; } catch (error) { hide(); message.error('修改失败请重试!'); return false; } }; const labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'] // 模拟考试规则维护 export default () => { const [selectorModalVisible, handleSelectorModalVisible] = useState(false); const [scoreModalVisible, handleScoreModalVisible] = useState(false); const [autoModalVisible, handleAutoModalVisible] = useState(false); const [subjectId, setSubjectId] = useState(0); // 关联主题id const [subjectName, setSubjectName] = useState(''); // 关联主题name const [questionTypeValues, setQuestionTypeValues] = useState([]); // 题型数据[{count:0, score:0, score_harf:0}] const [uuidPaper, setUuidPaper] = useState(0); const [createType, setCreateType] = useState(1); // 组卷类型 const [rulesName, setRulesName] = useState(''); // 组卷类型 const [sumScore, setSumScore] = useState(0); // 总分 const [passScore, setPassScore] = useState(0); // 通过分数线 const [typeQuestionCount, setTypeQuestionCount] = useState([0, 0, 0]); // 临时卷 各题型数量 const [rulesId, setRulesId] = useState(0); // 规则id, 保存新建的rules_id const formRef = useRef(); const selectorRef = useRef(); const setterRef = useRef(); const autoRef = useRef(); const [currentStep, setCurrentStep] = useState(0); const params = useParams(); const [questionType, setQuestionType] = useState([]); // 题型 const [scoreValues, setScoreValues] = useState([]); // 分值 [{"question_type": "0","score": "3","score_harf": "0"},] const [paperInfo, setPaperInfo] = useState({}) /** 获取题型 */ const { data: questionTypeData } = useRequest(() => { return queryQuestionType(); }, { formatResult: (result) => { return result.list; } }); useEffect(() => { setQuestionType(questionTypeData || []); return () => { /** 退出当前页面清空Map */ //parsingMap.clear(); } }, [questionTypeData]); /** 组卷,查询试题临时表(当前选题列表) */ const { data: questions, run } = useRequest(async (params) => { console.log('questions', questions) const _data = await queryTempQuestionList(params); return _data; }, { manual: true, formatResult: (result) => { return result?.table_List; } }); /** 从临时表中计算各题型数量 */ useEffect(() => { const _data = [0, 0, 0]; // 当前仅支持 单选 / 多选 / 判断 的顺序 console.log('questions-info', questions) questions?.forEach((item) => { _data[Number(item?.question_type)] += 1 }) setTypeQuestionCount(_data); return () => { /** 退出当前页面清空Map */ //parsingMap.clear(); } }, [questions]); // const { data: paperData, run: runPaper } = useRequest(async (params) => { console.log('paperData', paperData) /** * rules_id: params?.id, page_number: value.current, page_size: value.pageSize */ return queryRulesPaper(params); }, { manual: true, formatResult: (result) => { return result?.question_list; } }); useEffect(() => { console.log('paperData2', paperData) if (paperData?.length > 0) { console.log('paperData[0]', paperData[0]) setPaperInfo(paperData[0]) } console.log('PaperInfo', paperInfo) }, [paperData]); console.log(params, 'params'); let ruleData = {} // if (params?.id) { //console.log(JSON.stringify(params), "878"); const { data } = useRequest(async () => { return queryRulesView(params); }, { formatResult: (result) => { return result?.bean; } }); ruleData = data } console.log(ruleData, 'ruleData'); return ( formRef={formRef} onFinish={async (e) => { message.success('提交成功'); }} formProps={{ layout: "horizontal", labelCol: { span: 7 }, wrapperCol: { span: 12 }, validateMessages: { required: '此项为必填项', }, }} > name="base" title="模拟考试基本信息" stepProps={{ description: false, }} onFinish={async (fileds) => { if (params?.id) { fileds = { ...fileds, id: (params.id || rulesId) } } const { data } = await saveRules({ ...fileds, b_use: 0, rules_type: 0, }); setRulesId(data?.rules_id) // 保存规则id //run({paper_uuid:1}); // 获取当前选题列表 // console.log('模拟考试基本信息', fileds) setSubjectId(fileds?.subject_id) // 设置当前关联主题 setRulesName(fileds?.rules_name) // 设置模拟考试规则名称 console.log('fileds', fileds) console.log('formRef', formRef.current?.getFieldValue('')) // await waitTime(2000); setCurrentStep(1) // 设置步骤号 return true; }} > {ruleData && ( <> { const val = `${e.currentTarget?.value}`; if(val.length > 50) { e.currentTarget.value = val.slice(0,50) } } //style:{width: '100%'} }} rules={[ { required: true, message: '请输入考试名称' }, { pattern: /^[^\s]*$/, message: '禁止输入空格' } ]} /> { return querySubjectList().then(({ data }) => { console.log(data, 'querySubjectList') return data.list.map((item) => { if (item?.subject_id === ruleData?.subject_id) { setSubjectName(item?.subject_name) // 设置关联主题名称 console.log('label::', item?.subject_name) } return { label: item?.subject_name, value: item?.subject_id, }; }); }); }} onChange={(value) => { console.log('on change', value) }} rules={[{ required: true, message: '请选择主题' }]} name="subject_id" label="关联主题" /> { const val = `${e.currentTarget?.value}`; e.currentTarget.value = val.replace(/[^\d]|[0]/,'') if(val.length > 3) { e.currentTarget.value = val.slice(0,3) } } //style:{width: '100%'} }} initialValue={ruleData?.examination_time} rules={[ { required: true, message: '请输入考试时长' }, { pattern: /^[^\s]*$/, message: '禁止输入空格' }]} /> )} name="object" title="组卷" stepProps={{ description: false, }} onFinish={async () => { console.log(formRef.current?.getFieldsValue()); setCurrentStep(2) // 设置步骤号 //alert(params?.id || rulesId) let msg = '操作成功' if(!questions){ msg = '请选择试题' message.error(msg); return false; } // question 请选择试题 请选择试题 runPaper({ rules_id: params?.id || rulesId }) return true; }} >
{rulesName} {/** 一旦录入另一项将禁用,清空组卷后可选另一项 */} {questions ? { handleAutoModalVisible(true) }} onCancel={()=>{}} okText="是" cancelText="否" > : } {questions && {questions && questions.map((item, idx) => ( item &&
{idx + 1}. {item?.question_stem} {(item?.question_type === 0) && // 单选题
{item?.answers && item?.answers.map((anster, k) => (
{anster?.is_true === '0' && {labels[k]} } {anster?.is_true === '1' && {labels[k]} } {anster?.answer}
))}
} {(item?.question_type === 1) && // 多选题
{item?.answers && item?.answers.map((anster, k) => (
{anster?.is_true === '0' && {labels[k]} } {anster?.is_true === '1' && {labels[k]} } {anster?.answer}
))}
} {(item?.question_type === 2) && // 判断选题
{item?.answers && item?.answers.map((anster, k) => (
{anster?.is_true === '0' && {labels[k]} } {anster?.is_true === '1' && {labels[k]} } {anster?.answer}
))}
}
{ const success = await handleRemoveTempQuestion(uuidPaper, [{ question_id: item?.id }]); // 调用批量删除函数(如果接口不支持批量需要在service中处理) if (success) { run({ paper_uuid: uuidPaper, page_size: 1000, page_number: 1 }); // 获取当前选题列表 } }} >
))}
} {!questions && }
试卷信息与设置 共 {questions?.length} 题 {'-'} 分 {questionType.map((item) => { return {item?.name} 共 {typeQuestionCount[Number(item.code)]} 题 {'-'} 分 } )} 请选择试题组卷并设置分值后保存} placement="bottom" color='#108ee9'>
{ console.log(formRef.current?.getFieldsValue()); // 跳转到指定路由 history.push('/examinationrules/normal'); return true; }} > {currentStep === 2 && { console.log('rulesId...', rulesId) //{rules_id: rulesId} console.log('params...', params) const result = await queryRulesView({id: rulesId}) console.log('queryRulesView', result) const subjectInfo = await getSubjectInfo({ subject_id: result.bean.subject_id }) console.log('subjectInfo', subjectInfo) return { data: { ...result.bean, subject_name: subjectInfo.data.subject_name } }; }} extra={false} > (`${text} 分钟`)} /> { {/** 从试卷中读取 临时卷必须保存后才进入此页 */ } return 共 {paperInfo?.question_type_count?.map(item=>item.count)?.reduce((prev, curr)=>prev + curr)} 道题, {paperInfo?.sum_score || '-'} 分 {paperInfo?.question_type_count?.map(item=>({`${item?.type_name} ${item?.count} 道题 `}))} 通过线 {paperInfo?.pass_score || '-'} 分 }} /> }
{ console.log('v::::', values.name); const rows = selectorRef?.current?.getSelectedRowKeys() console.log('rows::::', rows); const { code, data: paper, msg } = await handleAppend(Number(params?.id || rulesId), rows, uuidPaper) console.log('paper', paper) setUuidPaper(paper?.paper_uuid) console.log('paper_uuid', paper?.paper_uuid) /** 回显临时表 */ run({ paper_uuid: paper?.paper_uuid, page_size: 1000, page_number: 1 }); // 获取当前选题列表 // message.success('提交成功'); handleSelectorModalVisible(false) return true; }} > {selectorModalVisible && } { const values = autoRef?.current.getData() console.log('data-v', values) //const values = [{"question_type":0,"chapter_list": [{ "chapter_id":76, "count":1 },{ "chapter_id":77, "count":1 }]}] const {code, data: paper, msg} = await autoPaper({rules_id: Number(params?.id || rulesId), auto_param: JSON.stringify(values)}) //console.log('paper', paper) setUuidPaper(paper?.paper_uuid) run({ paper_uuid: paper?.paper_uuid, page_size: 1000, page_number: 1 }); // 获取当前选题列表 message.success('提交成功'); handleAutoModalVisible(false) return true; }} > {autoModalVisible && } { console.log('typeQuestionCount', typeQuestionCount) const values = setterRef.current?.getData() // 获取题型分值数据 const passSocre = setterRef.current?.getValue() // 获取通过分数线 const sumCore = setterRef.current?.getSum() // 获取总分 if(passSocre > sumCore){ message.error('通过分数线不能大于总分,请修改通过分数线'); return false; } console.log('批量设置分值v::::2', values); // 题型分数 const { code, data: paper, msg } = await saveQuestionTypeScore({ rules_id: Number(params?.id || rulesId), type_score: JSON.stringify(values) }) const { success } = await updateScore({ rules_id: Number(params?.id || rulesId), pass_socre: passSocre, sum_score: sumCore }) //setSumScore(_sumScore) //console.log('paper', paper) // setUuidPaper(paper?.paper_uuid) // message.success('提交成功'); handleScoreModalVisible(false) return true; }} >
); };