import React from 'react'; import { Link } from 'react-router-dom'; import { Icon } from 'antd'; import './index.less'; import Page from '@src/containers/Page'; import { timeRange, getMap, formatDate } from '@src/services/Tools'; import UserLayout from '../../../layouts/User'; import UserTable from '../../../components/UserTable'; import UserAction from '../../../components/UserAction'; import UserPagination from '../../../components/UserPagination'; import { RealAuth } from '../../../components/OtherModal'; import Examination from '../../../components/Examination'; import VipRenew from '../../../components/VipRenew'; import Modal from '../../../components/Modal'; import menu, { refreshQuestionType, refreshStruct } from '../index'; import Tabs from '../../../components/Tabs'; import { TimeRange, QuestionType, AskTarget } from '../../../../Constant'; import { My } from '../../../stores/my'; import { OpenText } from '../../../components/Open'; const QuestionTypeMap = getMap(QuestionType, 'value', 'label'); const AskTargetMap = getMap(AskTarget, 'value', 'label'); const questionColumns = [ { key: 'questionType', width: 140, render(text, row) { return <div className="group"> <Link to={row.userQuestionId ? `/paper/question/${row.userQuestionId}` : `/question/detail/${row.questionNoId}`}>{QuestionTypeMap[text]}</Link> </div>; }, }, { key: 'title', width: 100, render(text, row) { return <div className="group"> <Link to={row.userQuestionId ? `/paper/question/${row.userQuestionId}` : `/question/detail/${row.questionNoId}`}>{text}</Link> </div>; }, }, { key: 'content', width: 540, render(text, row) { return <div className="group text-hidden"><Link to={row.userQuestionId ? `/paper/question/${row.userQuestionId}` : `/question/detail/${row.questionNoId}`}>{text}</Link></div>; }, }, ]; const contentColumns = [ { key: 'title', title: '笔记对象', width: 140, render(text) { return <div className="sub">{AskTargetMap[text]}</div>; }, }, { key: 'updateTime', title: '更新时间', width: 100, render(text) { return <div className="sub"> <div className="t-2 t-s-12">{text.split(' ')[0]}</div> <div className="t-6 t-s-12">{text.split(' ')[1]}</div> </div>; }, }, { key: 'content', title: '内容', width: 540, render(text) { return <OpenText>{text}</OpenText>; }, }, ]; export default class extends Page { constructor(props) { props.size = 10; super(props); } initState() { return { filterMap: {}, sortMap: {}, selectList: [], contentSelectList: [], allChecked: false, tab: 'exercise', timerange: 'today', }; } 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.timerange) { data.filterMap.timerange = data.timerange; } const [startTime, endTime] = timeRange(data.timerange); refreshQuestionType(this, data.subject, data.questionType, { all: true, needSentence: false, allSubject: true, }).then(({ questionTypes }) => { return refreshStruct(this, data.tab, data.one, data.two, { all: true, needPreview: false, needTextbook: false, }).then(({ structIds, latest, year }) => { My.listQuestionNote( Object.assign( { module: data.tab, questionTypes, structIds, latest, year, startTime, endTime }, this.state.search, { order: Object.keys(data.sortMap) .map(key => { return `${key} ${data.sortMap[key]}`; }) .join(','), }, ), ).then(result => { result.list = result.list.map(row => { row.key = row.questionNoId; row.group = true; row.questionType = row.question.questionType; row.title = row.questionNo.title; row.content = row.question.description; row.list = []; AskTarget.forEach((r) => { if (!row[`${r.value}Content`]) return; row.list.push({ title: r.value, key: `${row.key}|${r.value}`, updateTime: formatDate(row[`${r.value}Time`], 'YYYY-MM-DD HH:mm:ss'), content: row[`${r.value}Content`], }); }); return row; }); this.setState({ list: result.list, total: result.total, page: data.page }); }); }); }); } onTabChange(tab) { const data = { tab }; this.refreshQuery(data); } onFilter(value) { this.search(value, false); this.initData(); } onSearch(value) { this.search({ keyword: value }, false); 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 ? keys[index] : null, direction: keys.length ? value[keys[index]] : null }, false); } onChangePage(page) { this.search({ page }, false); this.initData(); } onAll(checked) { const { selectList, contentSelectList } = this.state; const { list = [] } = this.state; if (checked) { list.forEach(item => { if (selectList.indexOf(item.key) < 0) { selectList.push(item.key); } AskTarget.forEach((r) => { if (!item[`${r.value}Content`]) return; if (contentSelectList.indexOf(`${item.key}|${r.value}`) < 0) { contentSelectList.push(`${item.key}|${r.value}`); } }); }); } else { list.forEach(item => { const index = selectList.indexOf(item.key); if (index >= 0) { selectList.splice(index, 1); } AskTarget.forEach((r) => { if (!item[`${r.value}Content`]) return; const i = contentSelectList.indexOf(`${item.key}|${r.value}`); if (i >= 0) { contentSelectList.splice(i, 1); } }); }); } this.setState({ selectList, contentSelectList, allChecked: checked }); } onSelect(selectList, key, checked) { const { contentSelectList, list = [] } = this.state; if (checked) { const [item] = list.filter(row => row.key === key); if (item) { // 选中下面所有 AskTarget.forEach((r) => { if (!item[`${r.value}Content`]) return; if (contentSelectList.indexOf(`${item.key}|${r.value}`) < 0) { contentSelectList.push(`${item.key}|${r.value}`); } }); } } else { const [item] = list.filter(row => row.key === key); if (item) { // 取消下面所有 AskTarget.forEach((r) => { if (!item[`${r.value}Content`]) return; const index = contentSelectList.indexOf(`${item.key}|${r.value}`); if (index >= 0) { contentSelectList.splice(index, 1); } }); } } this.setState({ selectList, contentSelectList, allCheckbox: false }); } onSelectContent(contentSelectList, key, checked) { const { selectList, list = [] } = this.state; if (checked) { const [questionNoIdStr] = key.split('|'); const questionNoId = Number(questionNoIdStr); const [item] = list.filter(row => row.key === questionNoId); if (item) { // 选中上级 if (selectList.indexOf(item.key) < 0) { selectList.push(item.key); } } } this.setState({ selectList, contentSelectList }); } onAction(key) { const { info } = this.props.user; const { selectList, contentSelectList } = this.state; const questionNoMap = {}; let questionNoIds; switch (key) { case 'help': this.setState({ showTips: true }); return; case 'clear': if (selectList.length === 0 && contentSelectList === 0) { this.setState({ showWarn: true, warn: { title: '移除', content: '不可少于1题,请重新选择' } }); return; } contentSelectList.forEach(row => { const [questionNoIdStr, target] = row.split('|'); const questionNoId = Number(questionNoIdStr); if (!questionNoMap[questionNoId]) { questionNoMap[questionNoId] = { fields: 0 }; } questionNoMap[questionNoId][target] = ''; questionNoMap[questionNoId].fields += 1; }); questionNoIds = Object.keys(questionNoMap).filter(row => questionNoMap[row].fields < AskTarget.length); if (questionNoIds.length > 0) { Promise.all(questionNoIds.map(row => { return My.updateQuestionNote(row, questionNoMap); })) .then(() => { const clearList = Object.keys(questionNoMap).filter(row => questionNoMap[row].fields === AskTarget.length); if (clearList.length > 0) { this.clearNote(clearList); } else { this.refresh(); } }); } // this.setState({ showClearConfirm: true, clearInfo: { questionNoIds: selectList } }); break; case 'export': if (!info.vip) { this.setState({ showVip: true }); return; } if (selectList.length < 1) { this.setState({ showWarn: true, warn: { title: '导出', content: '不可小于1题,请重新选择' } }); return; } if (selectList.length > 100) { this.setState({ showWarn: true, warn: { title: '导出', content: '不可多余100题,请重新选择' } }); return; } contentSelectList.forEach(row => { const [questionNoIdStr, target] = row.split('|'); const questionNoId = Number(questionNoIdStr); if (!questionNoMap[questionNoId]) { questionNoMap[questionNoId] = { fields: 0 }; } questionNoMap[questionNoId][target] = ''; questionNoMap[questionNoId].fields += 1; }); questionNoIds = Object.keys(questionNoMap); this.setState({ showExportConfirm: true, exportInfo: { questionNoIds, questionNoMap } }); break; default: } } clearNote(list) { My.clearQuestionNote(list) .then(() => { this.refresh(); }) .catch(e => { this.setState({ warn: { title: '移除', content: e.message }, showClearConfirm: false }); }); } export() { const { exportInfo } = this.state; this.setState({ showExportWait: true, showExportConfirm: false, showExportAuthConfirm: false }); My.exportNoteQuestion(exportInfo) .then((result) => { openLink(`/export/${result}`); this.setState({ showExportWait: false }); }) .catch(e => { this.setState({ warn: { title: '导出', content: e.message }, showExportWait: false }); }); } renderView() { const { config } = this.props; return <UserLayout active={config.key} menu={menu} center={this.renderTable()} />; } renderTable() { const { tab, questionSubjectSelect, questionSubjectMap = {}, oneSelect, twoSelectMap = {}, filterMap = {}, sortMap = {}, list = [], } = this.state; const { selectList = [], contentSelectList = [], allChecked, page, total } = this.state; const { info } = this.props.user; return ( <div className="table-layout"> <Tabs border type="division" theme="theme" size="small" space={2.5} width={100} active={tab} tabs={[{ key: 'exercise', title: '练习' }, { key: 'examination', title: '模考' }]} onChange={key => this.onTabChange(key)} /> <UserAction search defaultSearch={filterMap.keyword} selectList={[ { children: [ { key: 'subject', placeholder: '学科', select: questionSubjectSelect, }, { placeholder: '题型', key: 'questionType', be: 'subject', selectMap: questionSubjectMap, }, ], }, { label: '范围', children: [ { key: 'one', placeholder: '全部', select: oneSelect, }, { key: 'two', be: 'one', placeholder: '全部', selectMap: twoSelectMap, }, ], }, { right: true, key: 'timerange', select: TimeRange, }, ]} filterMap={filterMap} onFilter={value => this.onFilter(value)} onSearch={value => this.onSearch(value)} /> <UserAction allCheckbox allChecked={allChecked} help btnList={[ { title: '删除', key: 'clear' }, { title: '导出', key: 'export', tag: 'vip', disabled: !info.vip }, ]} sortList={[{ right: true, label: '更新时间', key: 'update_time' }]} sortMap={sortMap} onSort={value => this.onSort(value)} onAll={checked => this.onAll(checked)} onAction={key => this.onAction(key)} /> {list.map((item, index) => { return ( <div className="group"> <UserTable theme="dark" border={false} size="small" select selectList={selectList} columns={questionColumns} data={[item]} onSelect={(l, key, checked) => this.onSelect(l, key, checked)} header={false} /> <UserTable border={false} size="small" select even="default" selectList={contentSelectList} columns={contentColumns} data={item.list} onSelect={(l, key, checked) => this.onSelectContent(l, key, checked)} header={index === 0} /> </div> ); })} {total > 0 && list.length > 0 && ( <UserPagination total={total} current={page} pageSize={this.state.search.size} onChange={p => this.onChangePage(p)} /> )} {this.renderModal()} </div> ); } renderModal() { const { showTips, showWarn, warn = {}, showClearConfirm, clearInfo = {}, showVip, showExamination, showReal, showExportWait, showExportConfirm, exportInfo = {} } = this.state; const { info } = this.props.user; return [ <Modal show={showTips} title="操作提示" confirmText="好的,知道了" btnAlign="center" onConfirm={() => this.setState({ showTips: false })}> <div className="flex-layout m-b-2"> <div className="flex-block"> <div className="t-1 t-s-18">组卷功能</div> <div className="t-2">操作数量:10-50;</div> <div className="t-2">注意事项:可跨题型、不可跨学科。</div> </div> <div className="flex-block"> <div className="t-1 t-s-18">导出功能</div> <div className="t-2">操作数量:1-100;</div> <div className="t-2">注意事项:“综合推理IR”暂时无法导出。</div> </div> </div> <div className="t-3"> *您可点击 <Icon type="question-circle" theme="filled" /> 查阅以上信息。 </div> </Modal>, <Modal show={showWarn} title={warn.title} confirmText="好的,知道了" btnAlign="center" onConfirm={() => this.setState({ showWarn: false })}> <div className="t-2 t-s-18">{warn.content}</div> </Modal>, <Modal show={showClearConfirm} title="移出" onConfirm={() => this.clearNote()} onCancel={() => this.setState({ showClearConfirm: false })}> <div className="t-2 t-s-18"> 当前选中的 <span className="t-4">{clearInfo.questionNoIds ? clearInfo.questionNoIds.length : 0}</span> 道题即将被移出笔记,移出后无法恢复,是否继续? </div> </Modal>, <Modal show={showExportConfirm} title="导出" confirmText="导出" onConfirm={() => this.export()} onCancel={() => this.setState({ showExportConfirm: false })}> <div className="t-2 t-s-18 m-b-5"> 当前共选中 <span className="t-4">{exportInfo.questionNoIds ? exportInfo.questionNoIds.length : 0}</span> 道题笔记,是否开始导出: </div> </Modal>, <Modal show={showExportWait} title="导出" confirmText="好的,知道了" btnAlign="center" onConfirm={() => this.setState({ showExportWait: false })}> <div className="t-2 t-s-18">正在下载中,请不要关闭当前页面!</div> </Modal>, <Examination show={showExamination} data={info} onConfirm={() => this.setState({ showExamination: false })} onCancel={() => this.setState({ showExamination: false })} onClose={() => this.setState({ showExamination: false })} />, <RealAuth show={showReal} data={info} onConfirm={() => this.setState({ showReal: false })} />, <VipRenew show={showVip} data={info} onReal={() => this.setState({ showVip: false, showReal: true })} onPrepare={() => this.setState({ showVip: false, showExamination: true })} onClose={() => this.setState({ showVip: false })} />, ]; } }