import React, { Component } from 'react'; import './index.less'; import { Icon } from 'antd'; import { Link } from 'react-router-dom'; import Page from '@src/containers/Page'; import Assets from '@src/components/Assets'; import { getMap, formatPercent, formatSeconds } from '@src/services/Tools'; import Button from '../../../components/Button'; import Tabs from '../../../components/Tabs'; import UserAction from '../../../components/UserAction'; import UserPagination from '../../../components/UserPagination'; import { refreshQuestionType, refreshStruct } from '../index'; import { User } from '../../../stores/user'; import { Question } from '../../../stores/question'; import { QuestionType, QuestionDifficult } from '../../../../Constant'; import { My } from '../../../stores/my'; const QuestionTypeMap = getMap(QuestionType, 'value', 'label'); // const QuestionDifficultMap = getMap(QuestionDifficult, 'value', 'label'); export default class extends Page { initState() { this.searchNo = 0; return { list: [], searchList: [], keyword: '', subject: 'verbal', filterMap: {}, sortMap: {}, focus: false, difficultSelect: QuestionDifficult.map(row => { return { title: row.label, key: row.value, }; }), }; } initData() { const data = Object.assign(this.state, this.state.search); data.filterMap = this.state.search; if (data.order) { data.sortMap = { [data.order]: data.direction }; } if (data.subject) { data.filterMap.subject = data.subject; } this.setState(data); refreshQuestionType(this, data.subject, data.questionType, { needSentence: false, allSubject: true, excludeAwa: true, }).then(({ questionTypes }) => { return refreshStruct(this, questionTypes, 'exercise', data.one, data.two, { all: true, }).then(({ structIds }) => { let handler = null; if (this.state.search.keyword) { handler = Question.searchStem({ keyword: this.state.search.keyword, page: this.state.search.page, size: this.state.search.size, }); } else { handler = Question.searchStem( Object.assign({ questionTypes, structIds, module: 'exercise' }, this.state.search, { order: Object.keys(data.sortMap) .map(key => { return `${key} ${data.sortMap[key]}`; }) .join(','), }), ); } handler.then(result => { this.setState({ list: result.list, total: result.total, page: data.page, searchResult: !!data.keyword }); }); }); }); } onRefreshFilter(query) { // this.changeQuery(query); // this.setState(query); this.refreshQuery(query); // this.initData(); } onFilter(value) { this.search(value); // this.initData(); } onSearch(value) { const { keyword } = this.state; User.addSearch(value || keyword); // this.search({ page: 1, keyword }, false); // this.changeQuery({ keyword }); // this.setState({ keyword }); this.refreshQuery({ keyword: value || keyword }); // this.initData(); } onSort(value) { const keys = Object.keys(value); // this.search({ order: keys.length ? keys.join('|') : null, direction: keys.length ? Object.values(value).join('|') : null }); const { sortMap } = this.state; const index = keys.length > 1 && sortMap[keys[0]] ? 1 : 0; this.search({ order: keys.length && value[keys[index]] ? keys[index] : null, direction: keys.length ? value[keys[index]] : null }, false); this.initData(); } onChangePage(page) { this.search({ page }, false); this.initData(); } onChangeSearch(keyword, force = false) { if (!force) { this.searchNo += 1; const no = this.searchNo; Question.searchNo({ keyword, module: 'exercise', page: 1, size: 5 }).then(result => { if (no !== this.searchNo) return; this.setState({ searchList: result.list.map(row => row.title) }); }); } this.setState({ keyword }); } addSearchHistory(id) { My.addSearchHistory(id); } toggleCollect(index) { const { list } = this.props; const questionNo = list[index]; if (!questionNo.collect) { My.addQuestionCollect(questionNo.id).then(() => { questionNo.collect = true; questionNo.collectNumber += 1; this.setState({ list }); }); } else { My.delQuestionCollect(questionNo.id).then(() => { questionNo.collect = false; questionNo.collectNumber -= 1; this.setState({ list }); }); } } renderView() { const { searchResult } = this.state; return ( <div> {this.renderSearch()} {searchResult ? this.renderResult() : this.renderFilter()} </div> ); } renderSearch() { const { searchHistoryList = [] } = this.props.user; const { searchList = [], keyword, focus, tip } = this.state; // console.log(focus, tip, searchHistoryList); return ( <div className="search-layout"> <div className="search-wrapper"> <input value={keyword} onChange={e => this.onChangeSearch(e.target.value)} onFocus={() => this.setState({ focus: true })} onBlur={() => this.setState({ focus: false })} /> <Button width={150} onClick={() => this.onSearch(keyword)}> <Icon className="m-r-5" type="search" /> 搜索题目 </Button> {(focus || tip) && ( <div hidden={!keyword || searchList.length === 0} className="search-tip-wrapper" onMouseEnter={() => this.setState({ tip: true })} onMouseLeave={() => this.setState({ tip: false })} > {searchList.map(item => { return ( <div className="t-2 t-s-16" onClick={() => { // this.onChangeSearch(item, true); this.onSearch(item); }} > {item} </div> ); })} </div> )} {(focus || tip) && ( <div hidden={keyword || searchHistoryList.length === 0} className="search-tip-wrapper" onMouseEnter={() => this.setState({ tip: true })} onMouseLeave={() => this.setState({ tip: false })} > {searchHistoryList.map((item, index) => { return ( <div className="t-2 t-s-16" onClick={() => { // this.onChangeSearch(item, true); this.onSearch(item); }} > {item} <div className="f-r t-4 t-s-12 c-p" onClick={e => { e.stopPropagation(); User.removeSearchIndex(index); }} > 删除 </div> </div> ); })} <div className="all-del t-r"> <span className="t-4 t-s-12 c-p" onClick={() => User.clearSearch()}> 删除历史 </span> </div> </div> )} </div> </div> ); } renderFilter() { const { filterMap, sortMap } = this.state; const { subject, questionSubjectSelect, questionSubjectMap = {}, difficultSelect, oneSelect, twoSelectMap = {}, list = [], total, page, } = this.state; const { login } = this.props.user; return ( <div className="filter-layout"> <div className="content"> <div style={{ right: 0, top: 0 }} className="p-a" hidden={!login}> <Link to="/question/search/history"> <Assets name="history_time" className="m-r-5" /> 浏览历史 > </Link> </div> <Tabs border type="division" theme="theme" size="small" space={5} width={220} active={subject} tabs={questionSubjectSelect} onChange={key => this.onRefreshFilter({ subject: key })} /> <UserAction selectList={[ { key: 'questionType', placeholder: '题型', select: questionSubjectMap[subject] || [], }, { label: '范围', children: [ { key: 'one', placeholder: '全部', select: oneSelect, }, { placeholder: '全部', key: 'two', be: 'one', selectMap: twoSelectMap, }, ], }, { right: true, placeholder: '难度', key: 'level', select: difficultSelect, }, ]} sortList={[ { key: 'time', label: '全站用时', fixed: true, right: true }, { key: 'correct', label: '平均正确率', fixed: true, right: true }, { key: 'collect_number', label: '收藏人数', fixed: true, right: true }, ]} filterMap={filterMap} sortMap={sortMap} onSort={value => this.onSort(value)} onFilter={value => this.onFilter(value)} /> {this.renderList()} {total > 0 && list.length > 0 && ( <UserPagination total={total} current={page} pageSize={this.state.search.size} onChange={p => this.onChangePage(p)} /> )} </div> </div> ); } renderResult() { const { total, list, page } = this.state; return ( <div className="result-layout"> <div className="content"> <div className="m-b-1"> <span className="t-1 t-s-24">搜索结果:</span> <span className="t-2 t-s-18">共{total}条</span> </div> {this.renderList()} {total > 0 && list.length > 0 && ( <UserPagination total={total} current={page} pageSize={this.state.search.size} onChange={p => this.onChangePage(p)} /> )} </div> </div> ); } renderList() { const { list } = this.state; return list.map(item => { return <SearchItem data={item} onClick={() => this.addSearchHistory(item.id)} />; }); } } class SearchItem extends Component { render() { const { data = {}, onClick } = this.props; return ( <div className="search-item"> <div className="search-item-head"> <span className="t-15 t-s-16 m-r-1">{QuestionTypeMap[data.question.questionType]}</span> <a className="t-1 t-s-16" href={`/question/detail/${data.id}`} target="_blank" onClick={() => onClick()}> {data.title} </a> <div className="f-r t-15 t-s-14"> <span className="m-r-1">{data.question.difficult}</span> <span className="m-r-1">用时: {formatSeconds(data.totalTime / data.totalNumer)}</span> <span className="m-r-1">{formatPercent(data.totalCorrect, data.totalNumber, false)}</span> <span>收藏 {data.collectNumber || 0}</span> </div> </div> <div className="t-1 p-20">{data.question.description}</div> </div> ); } }