123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- import React, { Component } from 'react';
- import './index.less';
- import Assets from '@src/components/Assets';
- import { formatSecond, formatPercent, formatSeconds } from '@src/services/Tools';
- import Icon from '../../../../components/Icon';
- import Button from '../../../../components/Button';
- import Switch from '../../../../components/Switch';
- import Tabs from '../../../../components/Tabs';
- import Progress from '../../../../components/Progress';
- import HardInput from '../../../../components/HardInput';
- import AnswerCheckbox from '../../../../components/AnswerCheckbox';
- import { SentenceOption } from '../../../../../Constant';
- import { Question } from '../../../../stores/question';
- export default class extends Component {
- constructor(props) {
- super(props);
- // 确保可以自身进行答案显示,外部也可以直接显示答案
- // 将props转入state
- this.state = {
- analysisTab: 'qx',
- focusKey: 'subject',
- scene: this.props.scene || 'answer',
- userQuestion: this.props.userQuestion,
- question: this.props.question,
- };
- const { question, userQuestion } = this.props;
- if (this.state.scene === 'answer') {
- this.state.stem = this.formatStem(question.stem, userQuestion.userAnswer, question.answer);
- } else {
- this.state.stem = question.stem;
- }
- }
- showAnswer() {
- const { userQuestion } = this.state;
- Question.getDetailById(userQuestion.id).then(result => {
- const { question } = result;
- this.setState({
- userQuestion: result,
- question: result.question,
- scene: 'answer',
- stem: this.formatStem(question.stem, result.userAnswer, question.answer),
- });
- });
- }
- addTarget(target) {
- const uuid = target.getAttribute('uuid');
- if (!uuid) return;
- const text = target.innerText;
- const { focusKey, answer = {}, question } = this.state;
- if (!answer[focusKey]) answer[focusKey] = [];
- if (answer[focusKey].filter(row => row.uuid === uuid).length > 0) return;
- answer[focusKey].push({
- text,
- uuid,
- });
- this.setState({
- answer,
- stem: this.formatStem(question.stem, answer),
- });
- }
- removeTarget(key, target) {
- const { answer = {}, question } = this.state;
- if (!answer[key]) return;
- answer[key] = answer[key].filter(row => row.uuid !== target.uuid);
- this.setState({
- answer,
- stem: this.formatStem(question.stem, answer),
- });
- }
- next() {
- const { flow } = this.props;
- const { scene } = this.state;
- if (scene === 'question') {
- const { answer } = this.state;
- flow.submit(answer).then(() => {
- this.showAnswer();
- });
- } else if (scene === 'answer') {
- flow.next();
- }
- }
- formatStem(stem, userAnswer, answer) {
- // userAnswer 添加蓝色字, 错误的添加红色背景
- // answer 添加绿色背景
- const uuidMap = {};
- const show = !!answer;
- answer = answer || {};
- userAnswer = userAnswer || {};
- Object.keys(userAnswer).forEach(key => {
- if (key === 'options') return;
- const u = userAnswer[key];
- const a = answer[key] && answer[key].length > 0 ? answer[key][0] : [];
- const map = {};
- a.forEach(row => {
- if (!uuidMap[row.uuid]) uuidMap[row.uuid] = [];
- uuidMap[row.uuid].push('true');
- map[row.uuid] = row;
- });
- u.forEach(row => {
- if (!uuidMap[row.uuid]) uuidMap[row.uuid] = [];
- uuidMap[row.uuid].push('user');
- if (show && !map[row.uuid]) uuidMap[row.uuid].push('false');
- });
- });
- Object.keys(uuidMap).forEach(uuid => {
- stem = stem.replace(`uuid='${uuid}'`, `uuid='${uuid}' class='${uuidMap[uuid].join(' ')}'`);
- });
- return stem;
- }
- renderHeader() {
- const { mode } = this.props;
- switch (mode) {
- case 'process':
- return this.renderProcessHeader();
- default:
- return this.renderQuestionHeader();
- }
- }
- renderProcessHeader() {
- const { userQuestion, singleTime, paper, flow } = this.props;
- return (
- <div className="layout-header">
- <div className="left">
- <div className="title">{paper.title}</div>
- </div>
- <div className="right">
- <div className="text">
- <Assets name="timecost_icon" />
- Time cost {formatSecond(userQuestion.userTime || singleTime)}
- </div>
- <Icon name="star" active={userQuestion.collect} onClick={() => flow.toggleCollect()} />
- </div>
- </div>
- );
- }
- renderQuestionHeader() {
- const { userQuestion, questionNo, paper, flow } = this.props;
- return (
- <div className="layout-header">
- <div className="left">
- <div className="title">{paper.title}</div>
- </div>
- <div className="right">
- <span className="b">
- 用时:
- <span
- dangerouslySetInnerHTML={{
- __html: formatSeconds(userQuestion.userTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '<span class="s">$1</span>$2'),
- }}
- />
- {/* 用时:<span className="s">1</span>m<span className="s">39</span>s */}
- </span>
- <span className="b">
- 全站:
- <span
- dangerouslySetInnerHTML={{
- __html: formatSeconds(questionNo.totalTime / questionNo.totalNumber).replace(
- /([0-9]+)(min|m|hour|h|s)/g,
- '<span class="s">$1</span>$2',
- ),
- }}
- />
- {/* 全站:<span className="s">1</span>m<span className="s">39</span>s */}
- </span>
- <span className="b">
- <span className="s">{formatPercent(questionNo.totalCorrect, questionNo.totalNumber)}</span>%
- </span>
- <Icon name="star" active={userQuestion.collect} onClick={() => flow.toggleCollect()} />
- </div>
- </div>
- );
- }
- render() {
- const { flow, paper, userQuestion } = this.props;
- return (
- <div id="paper-process-sentence">
- <div className="layout">
- {this.renderHeader()}
- {this.renderBody()}
- <div className="layout-footer">
- <div className="left">
- <Icon
- name={this.props.isFullscreenEnabled ? 'sceen-restore' : 'sceen-full'}
- onClick={() => flow.toggleFullscreen()}
- />
- </div>
- <div className="center">
- <div className="p">
- <Progress theme="theme" progress={formatPercent(userQuestion.no, paper.questionNumber)} />
- </div>
- <div className="t">
- {userQuestion.no}/{paper.questionNumber}
- </div>
- </div>
- <div className="right">
- <Button
- size="lager"
- radius
- onClick={() => {
- this.next();
- }}
- >
- Next <Assets name="next_icon" />
- </Button>
- </div>
- </div>
- </div>
- </div>
- );
- }
- renderBody() {
- const { scene } = this.state;
- switch (scene) {
- case 'question':
- return this.renderQuestion();
- case 'answer':
- return this.renderAnswer();
- default:
- return null;
- }
- }
- renderQuestion() {
- const { question } = this.props;
- const { focusKey, answer = {} } = this.state;
- const { stem } = question;
- return (
- <div className="layout-body">
- <div className="title">
- <Icon name="question" />
- 请分别找出句子中的主语,谓语和宾语,并做出逻辑关系判断。
- </div>
- <div
- className="desc"
- dangerouslySetInnerHTML={{ __html: stem }}
- onClick={e => {
- this.addTarget(e.target);
- }}
- />
- <div className="label">主语</div>
- <div className="input">
- <HardInput
- focus={focusKey === 'subject'}
- list={answer.subject || []}
- onClick={() => {
- this.setState({ focusKey: 'subject' });
- }}
- onDelete={item => {
- this.removeTarget('subject', item);
- }}
- />
- </div>
- <div className="label">谓语</div>
- <div className="input">
- <HardInput
- focus={focusKey === 'predicate'}
- list={answer.predicate || []}
- onClick={() => {
- this.setState({ focusKey: 'predicate' });
- }}
- onDelete={item => {
- this.removeTarget('predicate', item);
- }}
- />
- </div>
- <div className="label">宾语</div>
- <div className="input">
- <HardInput
- focus={focusKey === 'object'}
- list={answer.object || []}
- onClick={() => {
- this.setState({ focusKey: 'object' });
- }}
- onDelete={item => {
- this.removeTarget('object', item);
- }}
- />
- </div>
- <div className="select">
- <div className="select-title">本句存在以下哪种逻辑关系?(可多选)</div>
- <AnswerCheckbox
- list={SentenceOption}
- selected={answer.options}
- onChange={values => {
- answer.options = values;
- this.setState({ answer });
- }}
- />
- </div>
- </div>
- );
- }
- renderAnswer() {
- const { mode } = this.props;
- const { analysisTab, userQuestion, question, showAnswer, stem } = this.state;
- const { userAnswer = {} } = userQuestion;
- const { answer } = question;
- return (
- <div className="layout-body">
- {mode === 'question' ? (
- <Switch
- checked={showAnswer}
- onChange={value => {
- this.setState({ showAnswer: value });
- }}
- >
- {showAnswer ? '显示答案' : '关闭答案'}
- </Switch>
- ) : (<div className="title">
- <Icon name="question" />
- 请分别找出句子中的主语,谓语和宾语,并做出逻辑关系判断。
- </div>)}
- <div className="desc" dangerouslySetInnerHTML={{ __html: stem }} />
- <div className="label">主语</div>
- <div className="input">
- <HardInput show={showAnswer} list={userAnswer.subject || []} answer={answer.subject} />
- </div>
- <div className="label">谓语</div>
- <div className="input">
- <HardInput show={showAnswer} list={userAnswer.predicate || []} answer={answer.predicate} />
- </div>
- <div className="label">宾语</div>
- <div className="input">
- <HardInput show={showAnswer} list={userAnswer.object || []} answer={answer.object} />
- </div>
- <div className="select">
- <div className="select-title">本句存在以下哪种逻辑关系?(可多选)</div>
- <AnswerCheckbox
- show={showAnswer}
- list={SentenceOption}
- selected={userAnswer.options}
- answer={answer.options}
- />
- </div>
- {showAnswer && (
- <div className="analysis">
- <Tabs
- type="division"
- active={analysisTab}
- tabs={[{ key: 'qx', name: '解析详情' }, { key: 'chinese', name: '中文语意' }]}
- onChange={key => {
- this.setState({ analysisTab: key });
- }}
- />
- {this.renderText()}
- </div>
- )}
- </div>
- );
- }
- renderText() {
- const { analysisTab, question = {} } = this.state;
- let content;
- switch (analysisTab) {
- case 'chinese':
- content = (
- <div className="detail-block text-block" dangerouslySetInnerHTML={{ __html: question.chineseContent }} />
- );
- break;
- case 'qx':
- content = <div className="detail-block text-block u-s-n" dangerouslySetInnerHTML={{ __html: question.qxContent }} />;
- break;
- default:
- break;
- }
- return content;
- }
- }
|