Commit 6f9accee by wufan

feat:完成全局设置iconfontfontweight和助学工具替换默认图功能

parent 7638b279
...@@ -175,7 +175,10 @@ class AddLiveClass extends React.Component { ...@@ -175,7 +175,10 @@ class AddLiveClass extends React.Component {
<Tooltip <Tooltip
overlayStyle={{maxWidth: 300, zIndex: '9999'}} overlayStyle={{maxWidth: 300, zIndex: '9999'}}
title={<div style={{width: '266px'}}>支持按上课日期批量创建直播课,创建后按“课程名称_日期”命名,例如:<br/>张三的语文课_9月18日<br/>张三的语文课_9月19日......</div>}> title={<div style={{width: '266px'}}>支持按上课日期批量创建直播课,创建后按“课程名称_日期”命名,例如:<br/>张三的语文课_9月18日<br/>张三的语文课_9月19日......</div>}>
<span className="iconfont">&#xe61d;</span> <span
style={{ color: "rgba(191, 191, 191, 1)",fontWeight: 400 }}
className="iconfont"
>&#xe61d;</span>
</Tooltip> </Tooltip>
</span> </span>
<div> <div>
......
...@@ -147,7 +147,7 @@ class VideoCourseList extends React.Component { ...@@ -147,7 +147,7 @@ class VideoCourseList extends React.Component {
关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。 关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。
</div> </div>
}> }>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px' }}> <i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: 'normal' }}>
&#xe61d; &#xe61d;
</i> </i>
</Tooltip> </Tooltip>
......
...@@ -330,7 +330,7 @@ class UserLearningData extends React.Component { ...@@ -330,7 +330,7 @@ class UserLearningData extends React.Component {
<span> <span>
<span>学习进度</span> <span>学习进度</span>
<Tooltip title='学员培训计划中达到“已完成”状态的课程数/总课程数'> <Tooltip title='学员培训计划中达到“已完成”状态的课程数/总课程数'>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px' }}> <i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: 'normal' }}>
&#xe61d; &#xe61d;
</i> </i>
</Tooltip> </Tooltip>
......
import React, { useState, useRef, useEffect, useContext } from 'react'; import React, { useState, useRef, useEffect } from "react";
import Service from '@/common/js/service'; import Service from "@/common/js/service";
import { PageControl } from '@/components'; import { PageControl } from "@/components";
import { Input, Select, Tooltip, Button, Table } from 'antd'; import { Input, Select, Tooltip, Button } from "antd";
import User from '@/common/js/user'; import User from "@/common/js/user";
import moment from 'moment'; import { XMTable } from "@/components";
import './userData.less'; import college from "@/common/lottie/college.json";
const { Search } = Input; import "./userData.less";
const { Option } = Select;
interface sortType { interface sortType {
type: 'ascend' | 'descend' | null | undefined; type: "ascend" | "descend" | null | undefined;
} }
function ExamData(props: any) { function ExamData(props: any) {
...@@ -18,37 +17,37 @@ function ExamData(props: any) { ...@@ -18,37 +17,37 @@ function ExamData(props: any) {
}; };
const examDataInit: any = {}; const examDataInit: any = {};
const queryInit: any = { current: 1, size: 10, order: 'SORT_ASC' }; const queryInit: any = { current: 1, size: 10, order: "SORT_ASC" };
const [examData, setUserData] = useState(examDataInit); const [examData, setUserData] = useState(examDataInit);
const [list, setList] = useState([]); const [list, setList] = useState([]);
const [query, setQuery] = useState(queryInit); const [query, setQuery] = useState(queryInit);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [field, setfield] = useState(''); const [field, setfield] = useState("");
const [allData, setAllData] = useState(0); const [allData, setAllData] = useState(0);
const [order, setOrder] = useState(sortStatus.type); const [order, setOrder] = useState(sortStatus.type);
const questionTypeList = { const questionTypeList = {
SINGLE_CHOICE: '单选题', SINGLE_CHOICE: "单选题",
MULTI_CHOICE: '多选题', MULTI_CHOICE: "多选题",
JUDGE: '判断题', JUDGE: "判断题",
GAP_FILLING: '填空题', GAP_FILLING: "填空题",
INDEFINITE_CHOICE: '不定项选择题', INDEFINITE_CHOICE: "不定项选择题",
}; };
const userTypeEnum = { const userTypeEnum = {
WORK_WE_CHAT: '企业微信', WORK_WE_CHAT: "企业微信",
WE_CHAT: '微信', WE_CHAT: "微信",
}; };
const userExamStateEnum = { const userExamStateEnum = {
EXAM: '进行中', EXAM: "进行中",
LACK_EXAM: '缺考', LACK_EXAM: "缺考",
FINISH_EXAM: '已考试', FINISH_EXAM: "已考试",
}; };
const orderEnum = { const orderEnum = {
currentAccuracy: { currentAccuracy: {
ascend: 'ACCURACY_ASC', ascend: "ACCURACY_ASC",
descend: 'ACCURACY_DESC', descend: "ACCURACY_DESC",
}, },
}; };
...@@ -64,7 +63,7 @@ function ExamData(props: any) { ...@@ -64,7 +63,7 @@ function ExamData(props: any) {
}, [query]); }, [query]);
function queryExamUserData() { function queryExamUserData() {
Service.Hades('public/hades/queryExamQuestionData', { Service.Hades("public/hades/queryExamQuestionData", {
examId: props.examId, examId: props.examId,
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
...@@ -75,7 +74,7 @@ function ExamData(props: any) { ...@@ -75,7 +74,7 @@ function ExamData(props: any) {
} }
function queryExamUserDataList() { function queryExamUserDataList() {
Service.Hades('public/hades/queryExamQuestionDataList', { Service.Hades("public/hades/queryExamQuestionDataList", {
...query, ...query,
examId: props.examId, examId: props.examId,
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
...@@ -92,35 +91,38 @@ function ExamData(props: any) { ...@@ -92,35 +91,38 @@ function ExamData(props: any) {
const columns = [ const columns = [
{ {
title: '序号', title: "序号",
dataIndex: 'sort', dataIndex: "sort",
width: 60, width: 60,
render: (text: any, record: any, index: any) => <span>{index + 1}</span>, render: (text: any, record: any, index: any) => <span>{index + 1}</span>,
}, },
{ {
title: '题目', title: "题目",
dataIndex: 'questionStem', dataIndex: "questionStem",
ellipsis: true, ellipsis: true,
width: 350, width: 350,
render: (val: any) => { render: (val: any) => {
var handleVal = val; var handleVal = val;
handleVal = handleVal.replace(/<(?!img|input).*?>/g, ''); handleVal = handleVal.replace(/<(?!img|input).*?>/g, "");
handleVal = handleVal.replace(/<\s?input[^>]*>/gi, '_、'); handleVal = handleVal.replace(/<\s?input[^>]*>/gi, "_、");
handleVal = handleVal.replace(/\&nbsp\;/gi, ' '); handleVal = handleVal.replace(/\&nbsp\;/gi, " ");
return ( return (
<Tooltip <Tooltip
overlayClassName='aid-tool-list' overlayClassName="aid-tool-list"
title={<div style={{ maxWidth: 700, width: 'auto' }}>{handleVal}</div>} title={
placement='topLeft' <div style={{ maxWidth: 700, width: "auto" }}>{handleVal}</div>
overlayStyle={{ maxWidth: 700 }}> }
placement="topLeft"
overlayStyle={{ maxWidth: 700 }}
>
{handleVal} {handleVal}
</Tooltip> </Tooltip>
); );
}, },
}, },
{ {
title: '题型', title: "题型",
dataIndex: 'questionType', dataIndex: "questionType",
render: (text: any) => <span>{(questionTypeList as any)[text]}</span>, render: (text: any) => <span>{(questionTypeList as any)[text]}</span>,
filters: Object.keys(questionTypeList).map((key) => { filters: Object.keys(questionTypeList).map((key) => {
return { return {
...@@ -130,25 +132,33 @@ function ExamData(props: any) { ...@@ -130,25 +132,33 @@ function ExamData(props: any) {
}), }),
}, },
{ {
title: '本次正确率', title: "本次正确率",
dataIndex: 'currentAccuracy', dataIndex: "currentAccuracy",
sorter: true, sorter: true,
sortOrder: field === 'currentAccuracy' ? order : sortStatus.type, sortOrder: field === "currentAccuracy" ? order : sortStatus.type,
render: (text: any) => <span>{parseInt((text * 100) as any)}%</span>, render: (text: any) => <span>{parseInt((text * 100) as any)}%</span>,
}, },
{ {
title: ( title: (
<div> <div>
历史正确率{' '} 历史正确率{" "}
<Tooltip overlayClassName='tool-list' title='包含本次考试正确率' placement='top' overlayStyle={{ maxWidth: 700 }}> <Tooltip
{' '} overlayClassName="tool-list"
<span style={{ color: 'rgba(191, 191, 191, 1)' }} className='icon iconfont'> title="包含本次考试正确率"
placement="top"
overlayStyle={{ maxWidth: 700 }}
>
{" "}
<span
style={{ color: "rgba(191, 191, 191, 1)",fontWeight: 400 }}
className="icon iconfont"
>
&#xe61d; &#xe61d;
</span> </span>
</Tooltip> </Tooltip>
</div> </div>
), ),
dataIndex: 'totalAccuracy', dataIndex: "totalAccuracy",
render: (text: any) => <span>{parseInt((text * 100) as any)}%</span>, render: (text: any) => <span>{parseInt((text * 100) as any)}%</span>,
}, },
]; ];
...@@ -174,78 +184,97 @@ function ExamData(props: any) { ...@@ -174,78 +184,97 @@ function ExamData(props: any) {
} }
function download() { function download() {
Service.Hades('public/hades/exportExamData', { Service.Hades("public/hades/exportExamData", {
// ...query, // ...query,
examId: props.examId, examId: props.examId,
exportDataType: 'EXAM_QUESTION_DATA', exportDataType: "EXAM_QUESTION_DATA",
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
source: 0, source: 0,
}).then((res) => { }).then((res) => {
const dom = (document as any).getElementById('load-play-back-excel'); const dom = (document as any).getElementById("load-play-back-excel");
dom.setAttribute('href', res.result); dom.setAttribute("href", res.result);
dom.click(); dom.click();
}); });
} }
return ( return (
<div className='rr'> <div className="rr">
<a download id='load-play-back-excel' style={{ position: 'absolute', left: '-10000px' }}></a> <a
<div className='dataPanal'> download
id="load-play-back-excel"
style={{ position: "absolute", left: "-10000px" }}
></a>
<div className="dataPanal">
{!!examData.singleChoiceCnt && ( {!!examData.singleChoiceCnt && (
<div className='item'> <div className="item">
<div className='num'>{Math.round((examData.singleChoiceAccuracy || 0) * 100)}%</div> <div className="num">
<div className='percent'>正确率</div> {Math.round((examData.singleChoiceAccuracy || 0) * 100)}%
<div className='subTitle'> </div>
<div className='type'> <div className="percent">正确率</div>
<span className='icon iconfont'>&#xe7fa;</span>单选题 <span>(共{examData.singleChoiceCnt}题)</span> <div className="subTitle">
<div className="type">
<span className="icon iconfont">&#xe7fa;</span>单选题{" "}
<span>(共{examData.singleChoiceCnt}题)</span>
</div> </div>
</div> </div>
</div> </div>
)} )}
{!!examData.multiChoiceCnt && ( {!!examData.multiChoiceCnt && (
<div className='item'> <div className="item">
<div className='num'>{Math.round((examData.multiChoiceAccuracy || 0) * 100)}%</div> <div className="num">
<div className='percent'>正确率</div> {Math.round((examData.multiChoiceAccuracy || 0) * 100)}%
<div className='subTitle'> </div>
<div className='type'> <div className="percent">正确率</div>
<span className='icon iconfont'>&#xe7fb;</span>多选题<span>(共{examData.multiChoiceCnt}题)</span> <div className="subTitle">
<div className="type">
<span className="icon iconfont">&#xe7fb;</span>多选题
<span>(共{examData.multiChoiceCnt}题)</span>
</div> </div>
</div> </div>
</div> </div>
)} )}
{!!examData.judgeCnt && ( {!!examData.judgeCnt && (
<div className='item'> <div className="item">
<div className='num'>{Math.round((examData.judgeAccuracy || 0) * 100)}%</div> <div className="num">
<div className='percent'>正确率</div> {Math.round((examData.judgeAccuracy || 0) * 100)}%
<div className='subTitle'> </div>
<div className='type'> <div className="percent">正确率</div>
<span className='icon iconfont'>&#xe7fc;</span>判断题<span>(共{examData.judgeCnt}题)</span> <div className="subTitle">
<div className="type">
<span className="icon iconfont">&#xe7fc;</span>判断题
<span>(共{examData.judgeCnt}题)</span>
</div> </div>
</div> </div>
</div> </div>
)} )}
{!!examData.gapFillingCnt && ( {!!examData.gapFillingCnt && (
<div className='item'> <div className="item">
<div className='num'>{Math.round((examData.gapFillingAccuracy || 0) * 100)}%</div> <div className="num">
<div className='percent'>正确率</div> {Math.round((examData.gapFillingAccuracy || 0) * 100)}%
<div className='subTitle'> </div>
<div className='type'> <div className="percent">正确率</div>
<span className='icon iconfont'>&#xe7fd;</span>填空题<span>(共{examData.gapFillingCnt}题)</span> <div className="subTitle">
<div className="type">
<span className="icon iconfont">&#xe7fd;</span>填空题
<span>(共{examData.gapFillingCnt}题)</span>
</div> </div>
</div> </div>
</div> </div>
)} )}
{!!examData.indefiniteChoiceCnt && ( {!!examData.indefiniteChoiceCnt && (
<div className='item'> <div className="item">
<div className='num'>{Math.round((examData.indefiniteChoiceAccuracy || 0) * 100)}%</div> <div className="num">
<div className='percent'>正确率</div> {Math.round((examData.indefiniteChoiceAccuracy || 0) * 100)}%
<div className='subTitle'> </div>
<div className='type'> <div className="percent">正确率</div>
<span className='icon iconfont'>&#xe7fe;</span>不定项选择题 <span>(共{examData.indefiniteChoiceCnt}题)</span> <div className="subTitle">
<div className="type">
<span className="icon iconfont">&#xe7fe;</span>不定项选择题{" "}
<span>(共{examData.indefiniteChoiceCnt}题)</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -257,11 +286,22 @@ function ExamData(props: any) { ...@@ -257,11 +286,22 @@ function ExamData(props: any) {
</Button> </Button>
)} )}
<div className='content'> <div className="content">
<Table bordered size='small' columns={columns} dataSource={list} onChange={onChange} pagination={false}></Table> <XMTable
renderEmpty={{
image: college,
description: '暂无数据'
}}
bordered
size="small"
columns={columns}
dataSource={list}
onChange={onChange}
pagination={false}
></XMTable>
{total > 0 && ( {total > 0 && (
<PageControl <PageControl
size='small' size="small"
current={query.current - 1} current={query.current - 1}
pageSize={query.size} pageSize={query.size}
total={total} total={total}
......
...@@ -11,6 +11,8 @@ import { XMContext } from '@/store/context'; ...@@ -11,6 +11,8 @@ import { XMContext } from '@/store/context';
import ExamShareModal from './ExamShareModal'; import ExamShareModal from './ExamShareModal';
import DataAnalysic from './DataAnalysic'; import DataAnalysic from './DataAnalysic';
import PreviewModal from './PreviewModal'; import PreviewModal from './PreviewModal';
import college from '@/common/lottie/college.json';
import './index.less'; import './index.less';
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const { Search } = Input; const { Search } = Input;
...@@ -425,6 +427,7 @@ function ExaminationManager(props: any) { ...@@ -425,6 +427,7 @@ function ExaminationManager(props: any) {
pagination={false} pagination={false}
style={{ margin: '0px 0 16px' }} style={{ margin: '0px 0 16px' }}
renderEmpty={{ renderEmpty={{
image: college,
description: <span style={{ display: 'block', paddingBottom: 24 }}>暂无数据</span>, description: <span style={{ display: 'block', paddingBottom: 24 }}>暂无数据</span>,
}}></XMTable> }}></XMTable>
{total > 0 && ( {total > 0 && (
......
import React, { useState, useRef, useEffect } from 'react'; import React, { useState, useRef, useEffect } from "react";
import Service from '@/common/js/service'; import Service from "@/common/js/service";
import { PageControl } from '@/components'; import { PageControl } from "@/components";
import { Input, Select, Tooltip, Table, Button } from 'antd'; import { Input, Select, Tooltip, Table, Button } from "antd";
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from "antd/es/table";
import User from '@/common/js/user'; import User from "@/common/js/user";
import moment from 'moment'; import moment from "moment";
import './userData.less'; import { XMTable } from "@/components";
import college from "@/common/lottie/college.json";
import "./userData.less";
const { Search } = Input; const { Search } = Input;
const { Option } = Select; const { Option } = Select;
declare var window: any; declare var window: any;
interface sortType { interface sortType {
type: 'ascend' | 'descend' | null | undefined; type: "ascend" | "descend" | null | undefined;
} }
interface User { interface User {
key: number; key: number;
...@@ -29,45 +31,45 @@ function DataAnalysic(props: any) { ...@@ -29,45 +31,45 @@ function DataAnalysic(props: any) {
const [list, setList] = useState([]); const [list, setList] = useState([]);
const [query, setQuery] = useState(queryInit); const [query, setQuery] = useState(queryInit);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
const [field, setfield] = useState(''); const [field, setfield] = useState("");
const [allData, setAllData] = useState(0); const [allData, setAllData] = useState(0);
const [order, setOrder] = useState(sortStatus.type); const [order, setOrder] = useState(sortStatus.type);
const userTypeEnum = { const userTypeEnum = {
WORK_WE_CHAT: '企业微信', WORK_WE_CHAT: "企业微信",
WE_CHAT: '微信', WE_CHAT: "微信",
}; };
const userExamStateEnum = { const userExamStateEnum = {
EXAM: '进行中', EXAM: "进行中",
LACK_EXAM: '缺考', LACK_EXAM: "缺考",
FINISH_EXAM: '已考试', FINISH_EXAM: "已考试",
}; };
const ExamPassColorEnum = { const ExamPassColorEnum = {
EXAM_FAIL: 'rgba(255, 79, 79, 1)', EXAM_FAIL: "rgba(255, 79, 79, 1)",
EXAM_PASS: 'rgba(59, 189, 170, 1)', EXAM_PASS: "rgba(59, 189, 170, 1)",
}; };
const ExamPassEnum = { const ExamPassEnum = {
EXAM_FAIL: '不及格', EXAM_FAIL: "不及格",
EXAM_PASS: '及格', EXAM_PASS: "及格",
}; };
const userExamStateColorEnum = { const userExamStateColorEnum = {
EXAM: 'rgba(35, 143, 255, 1)', EXAM: "rgba(35, 143, 255, 1)",
LACK_EXAM: 'rgba(204, 204, 204, 1)', LACK_EXAM: "rgba(204, 204, 204, 1)",
FINISH_EXAM: 'rgba(47, 200, 60, 1)', FINISH_EXAM: "rgba(47, 200, 60, 1)",
}; };
const orderEnum = { const orderEnum = {
score: { score: {
ascend: 'EXAM_SCORE_ASC', ascend: "EXAM_SCORE_ASC",
descend: 'EXAM_SCORE_DESC', descend: "EXAM_SCORE_DESC",
}, },
userDuration: { userDuration: {
ascend: 'USER_DURATION_ASC', ascend: "USER_DURATION_ASC",
descend: 'USER_DURATION_DESC', descend: "USER_DURATION_DESC",
}, },
}; };
...@@ -83,7 +85,7 @@ function DataAnalysic(props: any) { ...@@ -83,7 +85,7 @@ function DataAnalysic(props: any) {
}, [query]); }, [query]);
function queryExamUserData() { function queryExamUserData() {
Service.Hades('public/hades/queryExamUserData', { Service.Hades("public/hades/queryExamUserData", {
examId: props.examId, examId: props.examId,
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
...@@ -94,7 +96,7 @@ function DataAnalysic(props: any) { ...@@ -94,7 +96,7 @@ function DataAnalysic(props: any) {
} }
function queryExamUserDataList() { function queryExamUserDataList() {
Service.Hades('public/hades/queryExamUserDataList', { Service.Hades("public/hades/queryExamUserDataList", {
...query, ...query,
examId: props.examId, examId: props.examId,
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
...@@ -111,79 +113,102 @@ function DataAnalysic(props: any) { ...@@ -111,79 +113,102 @@ function DataAnalysic(props: any) {
const columns: ColumnsType<User> = [ const columns: ColumnsType<User> = [
{ {
title: '学员', title: "学员",
dataIndex: 'userName', dataIndex: "userName",
render: (text: any, record: any) => ( render: (text: any, record: any) => (
<span> <span>
{text} {text}
<span style={{ color: record.userSource === 'WORK_WE_CHAT' ? 'rgba(255, 157, 20, 1)' : 'rgba(29, 204, 101, 1)' }}> <span
style={{
color:
record.userSource === "WORK_WE_CHAT"
? "rgba(255, 157, 20, 1)"
: "rgba(29, 204, 101, 1)",
}}
>
@{(userTypeEnum as any)[record.userSource]} @{(userTypeEnum as any)[record.userSource]}
</span> </span>
</span> </span>
), ),
}, },
{ {
title: '手机号', title: "手机号",
dataIndex: 'phone', dataIndex: "phone",
}, },
{ {
title: '考试状态', title: "考试状态",
dataIndex: 'userExamState', dataIndex: "userExamState",
render: (text: any) => ( render: (text: any) => (
<span> <span>
{' '} {" "}
<span className='exstatus' style={{ background: (userExamStateColorEnum as any)[text] }}></span> {(userExamStateEnum as any)[text]} <span
className="exstatus"
style={{ background: (userExamStateColorEnum as any)[text] }}
></span>{" "}
{(userExamStateEnum as any)[text]}
</span> </span>
), ),
}, },
{ {
title: '考试成绩', title: "考试成绩",
dataIndex: 'score', dataIndex: "score",
sorter: true, sorter: true,
sortOrder: field === 'score' ? order : sortStatus.type, sortOrder: field === "score" ? order : sortStatus.type,
render: (text: any, record: any) => ( render: (text: any, record: any) => (
<span> <span>
{' '} {" "}
{text}{' '} {text}{" "}
<span <span
style={{ style={{
border: `1px solid ${(ExamPassColorEnum as any)[record.examPass]}`, border: `1px solid ${
(ExamPassColorEnum as any)[record.examPass]
}`,
fontSize: 12, fontSize: 12,
color: (ExamPassColorEnum as any)[record.examPass], color: (ExamPassColorEnum as any)[record.examPass],
display: 'inline-block', display: "inline-block",
padding: '0px 2px', padding: "0px 2px",
}}> }}
>
{(ExamPassEnum as any)[record.examPass]} {(ExamPassEnum as any)[record.examPass]}
</span> </span>
</span> </span>
), ),
}, },
{ {
title: '进入考试时间', title: "进入考试时间",
dataIndex: 'examStartTime', dataIndex: "examStartTime",
render: (text: any) => <span>{moment(text).format('YYYY-MM-DD HH:mm')}</span>, render: (text: any) => (
<span>{moment(text).format("YYYY-MM-DD HH:mm")}</span>
),
}, },
{ {
title: '考试用时', title: "考试用时",
dataIndex: 'userDuration', dataIndex: "userDuration",
sorter: true, sorter: true,
sortOrder: field === 'userDuration' ? order : sortStatus.type, sortOrder: field === "userDuration" ? order : sortStatus.type,
render: (text: any, record: any) => <span>{record.userExamState === 'FINISH_EXAM' ? window.formatHourTime(text) : '-'} </span>, render: (text: any, record: any) => (
<span>
{record.userExamState === "FINISH_EXAM"
? window.formatHourTime(text)
: "-"}{" "}
</span>
),
}, },
//TODO: //TODO:
{ {
title: '操作', title: "操作",
key: '', key: "",
dataIndex: 'edit', dataIndex: "edit",
render: (value: any, record: any) => { render: (value: any, record: any) => {
return ( return (
<Choose> <Choose>
<When condition={record.userExamState === 'FINISH_EXAM'}> <When condition={record.userExamState === "FINISH_EXAM"}>
<div <div
className='answer-detail' className="answer-detail"
onClick={() => { onClick={() => {
checkAnswerDetail(record); checkAnswerDetail(record);
}}> }}
>
答题详情 答题详情
</div> </div>
</When> </When>
...@@ -204,16 +229,16 @@ function DataAnalysic(props: any) { ...@@ -204,16 +229,16 @@ function DataAnalysic(props: any) {
} }
function download() { function download() {
Service.Hades('public/hades/exportExamData', { Service.Hades("public/hades/exportExamData", {
// ...query, // ...query,
examId: props.examId, examId: props.examId,
exportDataType: 'EXAM_USER_DATA', exportDataType: "EXAM_USER_DATA",
tenantId: User.getStoreId(), tenantId: User.getStoreId(),
userId: User.getStoreUserId(), userId: User.getStoreUserId(),
source: 0, source: 0,
}).then((res) => { }).then((res) => {
const dom = (document as any).getElementById('load-play-back-excel'); const dom = (document as any).getElementById("load-play-back-excel");
dom.setAttribute('href', res.result); dom.setAttribute("href", res.result);
dom.click(); dom.click();
}); });
} }
...@@ -227,69 +252,92 @@ function DataAnalysic(props: any) { ...@@ -227,69 +252,92 @@ function DataAnalysic(props: any) {
} }
return ( return (
<div className='rr'> <div className="rr">
<a target='_blank' download id='load-play-back-excel' style={{ position: 'absolute', left: '-10000px' }}> <a
target="_blank"
download
id="load-play-back-excel"
style={{ position: "absolute", left: "-10000px" }}
>
111 111
</a> </a>
<div className='dataPanal'> <div className="dataPanal">
<div className='item'> <div className="item">
<div className='num'>{useData.joinCnt || 0}</div> <div className="num">{useData.joinCnt || 0}</div>
<div className='percent'></div> <div className="percent"></div>
<div className='subTitle'>参与人数</div> <div className="subTitle">参与人数</div>
</div> </div>
<div className='item'> <div className="item">
<div className='num'>{useData.finishCnt || 0}</div> <div className="num">{useData.finishCnt || 0}</div>
<div className='percent'>占比{parseInt(((useData.finishCnt || 0) / (useData.joinCnt || 1)) * 100 + '')}%</div> <div className="percent">
<div className='subTitle'>完成考试数 (人)</div> 占比
{parseInt(
((useData.finishCnt || 0) / (useData.joinCnt || 1)) * 100 + ""
)}
%
</div>
<div className="subTitle">完成考试数 (人)</div>
</div> </div>
<div className='item'> <div className="item">
<div className='num'>{useData.passCnt || 0}</div> <div className="num">{useData.passCnt || 0}</div>
<div className='percent'>占比{parseInt(((useData.passCnt || 0) / (useData.finishCnt || 1)) * 100 + '')}%</div> <div className="percent">
<div className='subTitle'>及格数 (人)</div> 占比
{parseInt(
((useData.passCnt || 0) / (useData.finishCnt || 1)) * 100 + ""
)}
%
</div>
<div className="subTitle">及格数 (人)</div>
</div> </div>
<div className='item'> <div className="item">
<div className='num'>{useData.averageScore || 0}</div> <div className="num">{useData.averageScore || 0}</div>
<div className='percent'>总分{props.examDetail?.examPaper?.totalScore}</div> <div className="percent">
<div className='subTitle'>平均分</div> 总分{props.examDetail?.examPaper?.totalScore}
</div>
<div className="subTitle">平均分</div>
</div> </div>
<div className='item'> <div className="item">
<div className='num'> {window.formatHourTime(useData.averageDuration || 0)} </div> <div className="num">
<div className='percent'></div> {" "}
<div className='subTitle'>平均用时</div> {window.formatHourTime(useData.averageDuration || 0)}{" "}
</div>
<div className="percent"></div>
<div className="subTitle">平均用时</div>
</div> </div>
</div> </div>
<div className='xm-search-filter' style={{ marginTop: '24px' }}> <div className="xm-search-filter" style={{ marginTop: "24px" }}>
<div style={{ display: 'flex' }}> <div style={{ display: "flex" }}>
<div className='search-condition'> <div className="search-condition">
<div className='search-condition__item'> <div className="search-condition__item">
<span className='search-name'>学员:</span> <span className="search-name">学员:</span>
<Search <Search
value={query.examName} value={query.examName}
className='search-input' className="search-input"
placeholder='搜索学员名或手机号' placeholder="搜索学员名或手机号"
onChange={(e) => { onChange={(e) => {
const _query = { ...query }; const _query = { ...query };
_query.searchKey = e.target.value; _query.searchKey = e.target.value;
setQuery(_query); setQuery(_query);
}} }}
onSearch={() => {}} onSearch={() => {}}
enterButton={<span className='icon iconfont'>&#xe832;</span>} enterButton={<span className="icon iconfont">&#xe832;</span>}
/> />
</div> </div>
<div className='search-condition__item'> <div className="search-condition__item">
<span className='search-name'>学员类型:</span> <span className="search-name">学员类型:</span>
<Select <Select
value={query.userSource} value={query.userSource}
placeholder='请选择学员类型' placeholder="请选择学员类型"
onChange={(val) => { onChange={(val) => {
const _query = { ...query }; const _query = { ...query };
_query.userSource = val; _query.userSource = val;
setQuery(_query); setQuery(_query);
}} }}
className='search-input' className="search-input"
allowClear> allowClear
>
{Object.keys(userTypeEnum).map((key: any) => { {Object.keys(userTypeEnum).map((key: any) => {
return ( return (
<Option value={key} key={key}> <Option value={key} key={key}>
...@@ -300,18 +348,19 @@ function DataAnalysic(props: any) { ...@@ -300,18 +348,19 @@ function DataAnalysic(props: any) {
</Select> </Select>
</div> </div>
<div className='search-condition__item'> <div className="search-condition__item">
<span className='search-name'>考试状态:</span> <span className="search-name">考试状态:</span>
<Select <Select
value={query.userExamState} value={query.userExamState}
placeholder='请选择考试状态' placeholder="请选择考试状态"
onChange={(val) => { onChange={(val) => {
const _query = { ...query }; const _query = { ...query };
_query.userExamState = val; _query.userExamState = val;
setQuery(_query); setQuery(_query);
}} }}
className='search-input' className="search-input"
allowClear> allowClear
>
{Object.keys(userExamStateEnum).map((key: any) => { {Object.keys(userExamStateEnum).map((key: any) => {
return ( return (
<Option value={key} key={key}> <Option value={key} key={key}>
...@@ -322,15 +371,16 @@ function DataAnalysic(props: any) { ...@@ -322,15 +371,16 @@ function DataAnalysic(props: any) {
</Select> </Select>
</div> </div>
</div> </div>
<div className='reset-fold-area'> <div className="reset-fold-area">
<Tooltip title='清空筛选'> <Tooltip title="清空筛选">
<span <span
className='resetBtn iconfont icon' className="resetBtn iconfont icon"
onClick={() => { onClick={() => {
setfield(''); setfield("");
setQuery({ current: 1, size: 10 }); setQuery({ current: 1, size: 10 });
}}> }}
&#xe61b;{' '} >
&#xe61b;{" "}
</span> </span>
</Tooltip> </Tooltip>
</div> </div>
...@@ -342,11 +392,23 @@ function DataAnalysic(props: any) { ...@@ -342,11 +392,23 @@ function DataAnalysic(props: any) {
</Button> </Button>
)} )}
<div className='content analysic-content'> <div className="content analysic-content">
<Table bordered size='small' rowClassName='analysic-content-row' columns={columns} dataSource={list} onChange={onChange} pagination={false}></Table> <XMTable
renderEmpty={{
image: college,
description: '暂无数据'
}}
bordered
size="small"
rowClassName="analysic-content-row"
columns={columns}
dataSource={list}
onChange={onChange}
pagination={false}
></XMTable>
{total > 0 && ( {total > 0 && (
<PageControl <PageControl
size='small' size="small"
current={query.current - 1} current={query.current - 1}
pageSize={query.size} pageSize={query.size}
total={total} total={total}
......
...@@ -31,6 +31,8 @@ import _ from "underscore"; ...@@ -31,6 +31,8 @@ import _ from "underscore";
import PaperPreviewModal from "../modal/PreviewPaperModal"; import PaperPreviewModal from "../modal/PreviewPaperModal";
import MoveModal from '../../modal/MoveModal'; import MoveModal from '../../modal/MoveModal';
import Bus from "@/core/bus"; import Bus from "@/core/bus";
import college from '@/common/lottie/college';
const { Search } = Input; const { Search } = Input;
...@@ -625,6 +627,7 @@ class PaperList extends Component { ...@@ -625,6 +627,7 @@ class PaperList extends Component {
bordered bordered
loading={loading} loading={loading}
renderEmpty={{ renderEmpty={{
image: college,
description: <span style={{ display: 'block', paddingBottom: 24 }}>还没有试卷</span> description: <span style={{ display: 'block', paddingBottom: 24 }}>还没有试卷</span>
}} }}
/> />
...@@ -641,6 +644,7 @@ class PaperList extends Component { ...@@ -641,6 +644,7 @@ class PaperList extends Component {
pagination={false} pagination={false}
bordered bordered
renderEmpty={{ renderEmpty={{
image: college,
description: <span style={{ display: 'block', paddingBottom: 24 }}>还没有试卷</span> description: <span style={{ display: 'block', paddingBottom: 24 }}>还没有试卷</span>
}} }}
/> />
......
...@@ -25,6 +25,8 @@ import AidToolService from "@/domains/aid-tool-domain/AidToolService"; ...@@ -25,6 +25,8 @@ import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import _ from "underscore"; import _ from "underscore";
import Bus from "@/core/bus"; import Bus from "@/core/bus";
import moment from 'moment'; import moment from 'moment';
import { XMTable } from '@/components';
import college from '@/common/lottie/college';
const { Search } = Input; const { Search } = Input;
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
...@@ -201,19 +203,6 @@ class SelectQuestionList extends Component { ...@@ -201,19 +203,6 @@ class SelectQuestionList extends Component {
return columns; return columns;
}; };
// 自定义表格空状态
customizeRenderEmpty = () => {
return (
<Empty
image="https://image.xiaomaiketang.com/xm/emptyTable.png"
imageStyle={{
height: 100,
}}
description={"还没有题目"}
></Empty>
);
};
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return; return;
...@@ -431,8 +420,11 @@ class SelectQuestionList extends Component { ...@@ -431,8 +420,11 @@ class SelectQuestionList extends Component {
)} )}
</div> </div>
<div className="select-question-content"> <div className="select-question-content">
<ConfigProvider renderEmpty={this.customizeRenderEmpty}> <XMTable
<Table renderEmpty={{
image: college,
description: '还没有题目'
}}
rowSelection={rowSelection} rowSelection={rowSelection}
rowKey={(record) => record.id} rowKey={(record) => record.id}
dataSource={dataSource} dataSource={dataSource}
...@@ -441,7 +433,6 @@ class SelectQuestionList extends Component { ...@@ -441,7 +433,6 @@ class SelectQuestionList extends Component {
onChange={this.handleChangeTable} onChange={this.handleChangeTable}
bordered bordered
/> />
</ConfigProvider>
<div className="box-footer"> <div className="box-footer">
<PageControl <PageControl
current={current - 1} current={current - 1}
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Table, ConfigProvider, Empty, Row, Input, Select, Tooltip, Space, Button, Modal, message, Menu, Dropdown, DatePicker } from 'antd'; import { Row, Input, Select, Tooltip, Space, Button, Modal, message, Menu, Dropdown, DatePicker } from 'antd';
import _ from 'underscore'; import _ from 'underscore';
import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter } from 'react-router-dom';
import { DownOutlined } from '@ant-design/icons'; import { DownOutlined } from '@ant-design/icons';
...@@ -21,6 +21,8 @@ import Bus from '@/core/bus'; ...@@ -21,6 +21,8 @@ import Bus from '@/core/bus';
import moment from 'moment'; import moment from 'moment';
import Service from '@/common/js/service'; import Service from '@/common/js/service';
import MoveModal from '../../modal/MoveModal'; import MoveModal from '../../modal/MoveModal';
import college from '@/common/lottie/college';
import './QuestionList.less'; import './QuestionList.less';
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
...@@ -671,6 +673,7 @@ class QuestionList extends Component { ...@@ -671,6 +673,7 @@ class QuestionList extends Component {
onChange={this.handleChangeTable} onChange={this.handleChangeTable}
rowSelection={rowSelection} rowSelection={rowSelection}
renderEmpty={{ renderEmpty={{
image: college,
description: ( description: (
<span style={{ display: 'block', paddingBottom: 24 }}> <span style={{ display: 'block', paddingBottom: 24 }}>
<span>还没有题目</span> <span>还没有题目</span>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment