Commit 29c47994 by yuananting

fix:解决合并培训计划空状态图的分支冲突

parents 96753369 1be68445
import React from 'react'; import React from 'react';
import { withRouter } from "react-router-dom"; import { withRouter } from 'react-router-dom';
import {Table, Modal,Input,message} from 'antd'; import { Input } from 'antd';
import { PageControl } from "@/components"; import { PageControl, XMTable } from '@/components';
import PlanService from '@/domains/plan-domain/planService' import college from '@/common/lottie/college';
import PlanService from '@/domains/plan-domain/planService';
import User from '@/common/js/user'; import User from '@/common/js/user';
import Bus from '@/core/bus'; import Bus from '@/core/bus';
import './EmployeeShareData.less'; import './EmployeeShareData.less';
...@@ -10,103 +11,129 @@ import './EmployeeShareData.less'; ...@@ -10,103 +11,129 @@ import './EmployeeShareData.less';
const { Search } = Input; const { Search } = Input;
const UserRole = { const UserRole = {
Store_Manager: { Store_Manager: {
text: "学院管理员" text: '学院管理员',
}, },
Cloud_Manager: { Cloud_Manager: {
text:"管理员" text: '管理员',
}, },
Cloud_Operator: { Cloud_Operator: {
text:'运营师' text: '运营师',
}, },
Cloud_Lecture: { Cloud_Lecture: {
text:"讲师" text: '讲师',
}, },
}; };
class EmployeeShareData extends React.Component { class EmployeeShareData extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const id = getParameterByName("id"); const id = getParameterByName('id');
this.state = { this.state = {
id, id,
dataSource:[], dataSource: [],
size:10, size: 10,
query: { query: {
current: 1, current: 1,
}, },
totalCount:0, totalCount: 0,
} };
} }
componentDidMount(){ componentDidMount() {
this.handleFetchDataList(); this.handleFetchDataList();
} }
handleFetchDataList = ()=>{ handleFetchDataList = () => {
const { query ,size,id} = this.state; const { query, size, id } = this.state;
const params ={ const params = {
...query, ...query,
size, size,
planId:id, planId: id,
storeId:User.getStoreId(), storeId: User.getStoreId(),
} };
PlanService.getPlanUserRecordPage(params).then((res) => { PlanService.getPlanUserRecordPage(params).then((res) => {
const { result = {} } = res ; const { result = {} } = res;
const { records = [], total = 0 } = result; const { records = [], total = 0 } = result;
this.setState({ this.setState({
dataSource: records, dataSource: records,
totalCount: Number(total) totalCount: Number(total),
}); });
}); });
} };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return;
} }
this.setState({ this.setState(
size {
},()=>{this.handleFetchDataList()}) size,
} },
handleChangeTable = (pagination, filters, sorter)=> { () => {
this.handleFetchDataList();
}
);
};
handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter; const { columnKey, order } = sorter;
const { query } = this.state; const { query } = this.state;
let _columnKey; let _columnKey;
let _order; let _order;
if (columnKey === 'learnNum' && order === 'ascend') { _columnKey="LEARN_NUM"; _order = 'SORT_ASC'; } if (columnKey === 'learnNum' && order === 'ascend') {
if (columnKey === 'learnNum' && order === 'descend') { _columnKey="LEARN_NUM"; _order = 'SORT_DESC'; } _columnKey = 'LEARN_NUM';
_order = 'SORT_ASC';
}
if (columnKey === 'learnNum' && order === 'descend') {
_columnKey = 'LEARN_NUM';
_order = 'SORT_DESC';
}
if (columnKey === 'learnFinishNum' && order === 'ascend') { _columnKey="FINISH_NUM"; _order = 'SORT_ASC'; } if (columnKey === 'learnFinishNum' && order === 'ascend') {
if (columnKey === 'learnFinishNum' && order === 'descend') { _columnKey="FINISH_NUM"; _order = 'SORT_DESC'; } _columnKey = 'FINISH_NUM';
_order = 'SORT_ASC';
}
if (columnKey === 'learnFinishNum' && order === 'descend') {
_columnKey = 'FINISH_NUM';
_order = 'SORT_DESC';
}
if (columnKey === 'learnNoFinishNum' && order === 'ascend') { _columnKey="NOT_NUM"; _order = 'SORT_ASC'; } if (columnKey === 'learnNoFinishNum' && order === 'ascend') {
if (columnKey === 'learnNoFinishNum' && order === 'descend') { _columnKey="NOT_NUM"; _order = 'SORT_DESC'; } _columnKey = 'NOT_NUM';
_order = 'SORT_ASC';
}
if (columnKey === 'learnNoFinishNum' && order === 'descend') {
_columnKey = 'NOT_NUM';
_order = 'SORT_DESC';
}
const _query = { const _query = {
...query, ...query,
sortMap:{} sortMap: {},
}; };
_query.sortMap[_columnKey]=_order; _query.sortMap[_columnKey] = _order;
this.setState(
{
query: _query,
},
() => this.handleFetchDataList()
);
};
handleChangNickname = (value) => {
const isPhone = (value || '').match(/^\d+$/);
const { query } = this.state;
if (isPhone) {
query.userPhone = value;
query.userName = null;
} else {
query.userName = value;
query.userPhone = null;
}
query.current = 1;
this.setState({ this.setState({
query:_query query,
},()=>this.handleFetchDataList()) });
} };
handleChangNickname = (value)=>{ watchDataView = (record) => {
const isPhone = (value || '').match(/^\d+$/); Bus.trigger('watchDataView', record);
const { query } = this.state; };
if(isPhone){
query.userPhone = value;
query.userName = null;
}else{
query.userName = value;
query.userPhone = null;
}
query.current = 1;
this.setState({
query
})
}
watchDataView = (record)=>{
Bus.trigger('watchDataView',record);
}
// 请求表头 // 请求表头
parselumns = () => { parselumns = () => {
const columns = [ const columns = [
...@@ -115,24 +142,16 @@ class EmployeeShareData extends React.Component { ...@@ -115,24 +142,16 @@ class EmployeeShareData extends React.Component {
key: 'storeUserName', key: 'storeUserName',
dataIndex: 'storeUserName', dataIndex: 'storeUserName',
render: (val, record) => { render: (val, record) => {
return ( return <div>{val}</div>;
<div> },
{val}
</div>
)
}
}, },
{ {
title: '角色', title: '角色',
key: 'roleEnum', key: 'roleEnum',
dataIndex: 'roleEnum', dataIndex: 'roleEnum',
render: (val, record) => { render: (val, record) => {
return ( return <div>{UserRole[record.roleEnum].text}</div>;
<div> },
{UserRole[record.roleEnum].text}
</div>
)
}
}, },
//产品暂时性隐藏 //产品暂时性隐藏
// { // {
...@@ -151,28 +170,20 @@ class EmployeeShareData extends React.Component { ...@@ -151,28 +170,20 @@ class EmployeeShareData extends React.Component {
title: '最近分享成功时间', title: '最近分享成功时间',
key: 'recentlyForwardTime', key: 'recentlyForwardTime',
dataIndex: 'recentlyForwardTime', dataIndex: 'recentlyForwardTime',
width:240, width: 240,
render: (val, record) => { render: (val, record) => {
return ( return <div>{formatDate('YYYY-MM-DD H:i', val)}</div>;
<div> },
{formatDate('YYYY-MM-DD H:i', val)}
</div>
)
}
}, },
{ {
title: '学习人数', title: '学习人数',
key: 'learnNum', key: 'learnNum',
dataIndex: 'learnNum', dataIndex: 'learnNum',
width:110, width: 110,
sorter:true, sorter: true,
render: (val, record) => { render: (val, record) => {
return ( return <div className='learn-num'>{val}</div>;
<div className="learn-num"> },
{val}
</div>
)
}
}, },
// { // {
// title: '已学完', // title: '已学完',
...@@ -208,51 +219,71 @@ class EmployeeShareData extends React.Component { ...@@ -208,51 +219,71 @@ class EmployeeShareData extends React.Component {
dataIndex: 'operate', dataIndex: 'operate',
render: (val, record) => { render: (val, record) => {
return ( return (
<span className="operate-item" onClick={()=>this.watchDataView(record)}>数据详情</span> <span className='operate-item' onClick={() => this.watchDataView(record)}>
) 数据详情
} </span>
} );
},
},
]; ];
return columns; return columns;
} };
render() { render() {
const { dataSource,query,size,totalCount} = this.state; const { dataSource, query, size, totalCount } = this.state;
return ( return (
<div className="employee-share-data"> <div className='employee-share-data'>
<div className="search-container"> <div className='search-container'>
<Search placeholder="搜索员工姓名或手机号" onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} style={{ width: 200 }} enterButton={<span className="icon iconfont">&#xe832;</span>}/> <Search
placeholder='搜索员工姓名或手机号'
onChange={(e) => {
this.handleChangNickname(e.target.value);
}}
onSearch={() => {
this.handleFetchDataList();
}}
style={{ width: 200 }}
enterButton={<span className='icon iconfont'>&#xe832;</span>}
/>
</div> </div>
<div> <div>
<Table <XMTable
rowKey={record => record.id} renderEmpty={{
dataSource={dataSource} image: college,
columns={this.parselumns()} description: '暂无数据',
pagination={false} }}
onChange={this.handleChangeTable} rowKey={(record) => record.id}
showSorterTooltip={false} dataSource={dataSource}
bordered columns={this.parselumns()}
pagination={false}
onChange={this.handleChangeTable}
showSorterTooltip={false}
bordered
/>
{dataSource.length > 0 && (
<div className='box-footer'>
<PageControl
current={query.current - 1}
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.setState(
{
query: _query,
},
() => {
this.handleFetchDataList();
}
);
}}
onShowSizeChange={this.onShowSizeChange}
/> />
{dataSource.length >0 && </div>
<div className="box-footer"> )}
<PageControl
current={query.current - 1}
pageSize={size}
total={totalCount}
toPage={(page) => {
const _query = {...query, current: page + 1};
this.setState({
query:_query
},()=>{ this.handleFetchDataList()})
}}
onShowSizeChange={this.onShowSizeChange}
/>
</div>
}
</div> </div>
</div> </div>
) );
} }
} }
export default withRouter(EmployeeShareData); export default withRouter(EmployeeShareData);
\ No newline at end of file
import React from 'react' import React from 'react';
import { withRouter } from 'react-router-dom' import { withRouter } from 'react-router-dom';
import { Table, Modal, message, Tooltip } from 'antd' import { Modal, message, Tooltip } from 'antd';
import { PageControl } from '@/components' import { PageControl, XMTable } from '@/components';
import UserLearningDataFilter from './UserLearningDataFilter' import college from '@/common/lottie/college';
import PlanService from '@/domains/plan-domain/planService' import UserLearningDataFilter from './UserLearningDataFilter';
import UserLearnDetailModal from '../modal/UserLearnDetailModal' import PlanService from '@/domains/plan-domain/planService';
import UnbundEmployeeModal from '../modal/UnbundEmployeeModal' import UserLearnDetailModal from '../modal/UserLearnDetailModal';
import User from '@/common/js/user' import UnbundEmployeeModal from '../modal/UnbundEmployeeModal';
import './UserLearningData.less' import User from '@/common/js/user';
const { confirm } = Modal import './UserLearningData.less';
const { confirm } = Modal;
const LearnState = { const LearnState = {
UN_PLAY: { UN_PLAY: {
text: '未开始', text: '未开始',
...@@ -19,12 +20,12 @@ const LearnState = { ...@@ -19,12 +20,12 @@ const LearnState = {
FINISH: { FINISH: {
text: '已完成', text: '已完成',
}, },
} };
class UserLearningData extends React.Component { class UserLearningData extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props);
const id = getParameterByName('id') const id = getParameterByName('id');
this.state = { this.state = {
id, id,
dataSource: [], dataSource: [],
...@@ -35,13 +36,13 @@ class UserLearningData extends React.Component { ...@@ -35,13 +36,13 @@ class UserLearningData extends React.Component {
totalCount: 0, totalCount: 0,
userLearnDetailModalSHow: false, userLearnDetailModalSHow: false,
unbundEmployeeModalVisible: false, unbundEmployeeModalVisible: false,
} };
} }
componentDidMount() { componentDidMount() {
this.handleFetchDataList() this.handleFetchDataList();
} }
handleFetchDataList = (_query) => { handleFetchDataList = (_query) => {
const { query, size, id } = this.state const { query, size, id } = this.state;
const params = { const params = {
...query, ...query,
..._query, ..._query,
...@@ -49,88 +50,88 @@ class UserLearningData extends React.Component { ...@@ -49,88 +50,88 @@ class UserLearningData extends React.Component {
planId: id, planId: id,
storeId: User.getStoreId(), storeId: User.getStoreId(),
storeUserId: User.getStoreUserId(), storeUserId: User.getStoreUserId(),
} };
this.setState({ query: params }) this.setState({ query: params });
PlanService.getPlanCustomerRecordPage(params).then((res) => { PlanService.getPlanCustomerRecordPage(params).then((res) => {
const { result = {} } = res const { result = {} } = res;
const { records = [], total = 0 } = result const { records = [], total = 0 } = result;
this.setState({ this.setState({
dataSource: records, dataSource: records,
totalCount: Number(total), totalCount: Number(total),
}) });
}) });
} };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return;
} }
this.setState( this.setState(
{ {
size, size,
}, },
() => { () => {
this.handleFetchDataList() this.handleFetchDataList();
} }
) );
} };
handleChangeTable = (pagination, filters, sorter) => { handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter const { columnKey, order } = sorter;
const { query } = this.state const { query } = this.state;
let _columnKey let _columnKey;
let _order let _order;
if (columnKey === 'latelyLearnTime' && order === 'ascend') { if (columnKey === 'latelyLearnTime' && order === 'ascend') {
_columnKey = 'LATE_LEARN_TIME' _columnKey = 'LATE_LEARN_TIME';
_order = 'SORT_ASC' _order = 'SORT_ASC';
} }
if (columnKey === 'latelyLearnTime' && order === 'descend') { if (columnKey === 'latelyLearnTime' && order === 'descend') {
_columnKey = 'LATE_LEARN_TIME' _columnKey = 'LATE_LEARN_TIME';
_order = 'SORT_DESC' _order = 'SORT_DESC';
} }
if (columnKey === 'startLearnTime' && order === 'ascend') { if (columnKey === 'startLearnTime' && order === 'ascend') {
_columnKey = 'START_LEARN_TIME' _columnKey = 'START_LEARN_TIME';
_order = 'SORT_ASC' _order = 'SORT_ASC';
} }
if (columnKey === 'startLearnTime' && order === 'descend') { if (columnKey === 'startLearnTime' && order === 'descend') {
_columnKey = 'START_LEARN_TIME' _columnKey = 'START_LEARN_TIME';
_order = 'SORT_DESC' _order = 'SORT_DESC';
} }
if (columnKey === 'learnNum' && order === 'ascend') { if (columnKey === 'learnNum' && order === 'ascend') {
_columnKey = 'LEARN_NUM' _columnKey = 'LEARN_NUM';
_order = 'SORT_ASC' _order = 'SORT_ASC';
} }
if (columnKey === 'learnNum' && order === 'descend') { if (columnKey === 'learnNum' && order === 'descend') {
_columnKey = 'LEARN_NUM' _columnKey = 'LEARN_NUM';
_order = 'SORT_DESC' _order = 'SORT_DESC';
} }
const _query = { const _query = {
...query, ...query,
sortMap: {}, sortMap: {},
} };
_query.sortMap[_columnKey] = _order _query.sortMap[_columnKey] = _order;
this.setState( this.setState(
{ {
query: _query, query: _query,
}, },
() => this.handleFetchDataList() () => this.handleFetchDataList()
) );
} };
watchDetail = (record) => { watchDetail = (record) => {
this.setState({ this.setState({
userLearnDetailModalSHow: true, userLearnDetailModalSHow: true,
storeCustomerId: record.storeCustomerId, storeCustomerId: record.storeCustomerId,
planId: record.planId, planId: record.planId,
}) });
} };
closeUserLearnDetailModal = () => { closeUserLearnDetailModal = () => {
this.setState({ this.setState({
userLearnDetailModalSHow: false, userLearnDetailModalSHow: false,
}) });
} };
UnbundEmployee = (record) => { UnbundEmployee = (record) => {
if (User.getUserRole() === 'CloudOperator') { if (User.getUserRole() === 'CloudOperator') {
return confirm({ return confirm({
...@@ -141,40 +142,40 @@ class UserLearningData extends React.Component { ...@@ -141,40 +142,40 @@ class UserLearningData extends React.Component {
okType: 'danger', okType: 'danger',
cancelText: '取消', cancelText: '取消',
onOk: () => { onOk: () => {
this.handleConfirmUnbundEmployee(record.storeCustomerId) this.handleConfirmUnbundEmployee(record.storeCustomerId);
}, },
}) });
} else { } else {
this.setState({ this.setState({
unbundEmployeeModalVisible: true, unbundEmployeeModalVisible: true,
storeCustomerId: record.storeCustomerId, storeCustomerId: record.storeCustomerId,
}) });
} }
} };
handleConfirmUnbundEmployee = (storeCustomerId) => { handleConfirmUnbundEmployee = (storeCustomerId) => {
let removeUserIds = [] let removeUserIds = [];
removeUserIds.push(storeCustomerId) removeUserIds.push(storeCustomerId);
const params = { const params = {
planId: getParameterByName('id'), planId: getParameterByName('id'),
removeUserIds, removeUserIds,
storeCustomerId: storeCustomerId, storeCustomerId: storeCustomerId,
storeId: User.getStoreId(), storeId: User.getStoreId(),
storeUserId: User.getStoreUserId(), storeUserId: User.getStoreUserId(),
} };
PlanService.removePlanCustomer(params).then((res) => { PlanService.removePlanCustomer(params).then((res) => {
this.handleFetchDataList() this.handleFetchDataList();
message.success('解绑成功') message.success('解绑成功');
}) });
} };
handleCloseUnbundEmployeeModal = () => { handleCloseUnbundEmployeeModal = () => {
this.setState({ this.setState({
unbundEmployeeModalVisible: false, unbundEmployeeModalVisible: false,
}) });
} };
// 请求表头 // 请求表头
parselumns = () => { parselumns = () => {
let columns let columns;
if (User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') { if (User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') {
columns = [ columns = [
{ {
...@@ -182,7 +183,7 @@ class UserLearningData extends React.Component { ...@@ -182,7 +183,7 @@ class UserLearningData extends React.Component {
key: 'storeCustomerName', key: 'storeCustomerName',
dataIndex: 'storeCustomerName', dataIndex: 'storeCustomerName',
render: (val, record) => { render: (val, record) => {
return <div>{val}</div> return <div>{val}</div>;
}, },
}, },
{ {
...@@ -190,14 +191,20 @@ class UserLearningData extends React.Component { ...@@ -190,14 +191,20 @@ class UserLearningData extends React.Component {
key: 'learnState', key: 'learnState',
dataIndex: 'learnState', dataIndex: 'learnState',
render: (val, record) => { render: (val, record) => {
return <div>{LearnState[val].text}</div> return <div>{LearnState[val].text}</div>;
}, },
}, },
{ {
title: <span> title: (
<span>负责人</span> <span>
<Tooltip title="培训计划的分享者/跟进人"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px',fontWeight:"400"}}>&#xe61d;</i></Tooltip> <span>负责人</span>
</span>, <Tooltip title='培训计划的分享者/跟进人'>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: '400' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: 'userNameList', key: 'userNameList',
dataIndex: 'userNameList', dataIndex: 'userNameList',
render: (val, record) => { render: (val, record) => {
...@@ -208,10 +215,10 @@ class UserLearningData extends React.Component { ...@@ -208,10 +215,10 @@ class UserLearningData extends React.Component {
<span> <span>
{item} {index < record.userNameList.length - 1 && <span></span>}{' '} {item} {index < record.userNameList.length - 1 && <span></span>}{' '}
</span> </span>
) );
})} })}
</div> </div>
) );
}, },
}, },
{ {
...@@ -221,7 +228,7 @@ class UserLearningData extends React.Component { ...@@ -221,7 +228,7 @@ class UserLearningData extends React.Component {
sorter: true, sorter: true,
width: 240, width: 240,
render: (val, record) => { render: (val, record) => {
return `${formatDate('YYYY-MM-DD H:i', parseInt(record.latelyLearnTime))}` return `${formatDate('YYYY-MM-DD H:i', parseInt(record.latelyLearnTime))}`;
}, },
}, },
{ {
...@@ -231,14 +238,20 @@ class UserLearningData extends React.Component { ...@@ -231,14 +238,20 @@ class UserLearningData extends React.Component {
width: 240, width: 240,
sorter: true, sorter: true,
render: (val, record) => { render: (val, record) => {
return <div>{formatDate('YYYY-MM-DD H:i', val)}</div> return <div>{formatDate('YYYY-MM-DD H:i', val)}</div>;
}, },
}, },
{ {
title: <span> title: (
<span>学习进度</span> <span>
<Tooltip title="学员培训计划中达到“已完成”状态的课程数/总课程数"><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px', fontWeight:"400"}}>&#xe61d;</i></Tooltip> <span>学习进度</span>
</span>, <Tooltip title='学员培训计划中达到“已完成”状态的课程数/总课程数'>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: '400' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: 'learnNum', key: 'learnNum',
dataIndex: 'learnNum', dataIndex: 'learnNum',
width: 130, width: 130,
...@@ -250,7 +263,7 @@ class UserLearningData extends React.Component { ...@@ -250,7 +263,7 @@ class UserLearningData extends React.Component {
<span>/</span> <span>/</span>
<span>{record.courseNum}</span> <span>{record.courseNum}</span>
</div> </div>
) );
}, },
}, },
{ {
...@@ -267,15 +280,15 @@ class UserLearningData extends React.Component { ...@@ -267,15 +280,15 @@ class UserLearningData extends React.Component {
<span <span
className='operate-item' className='operate-item'
onClick={() => { onClick={() => {
this.UnbundEmployee(record) this.UnbundEmployee(record);
}}> }}>
解绑 解绑
</span> </span>
</div> </div>
) );
}, },
}, },
] ];
} else { } else {
columns = [ columns = [
{ {
...@@ -283,7 +296,7 @@ class UserLearningData extends React.Component { ...@@ -283,7 +296,7 @@ class UserLearningData extends React.Component {
key: 'storeCustomerName', key: 'storeCustomerName',
dataIndex: 'storeCustomerName', dataIndex: 'storeCustomerName',
render: (val, record) => { render: (val, record) => {
return <div>{val}</div> return <div>{val}</div>;
}, },
}, },
{ {
...@@ -291,7 +304,7 @@ class UserLearningData extends React.Component { ...@@ -291,7 +304,7 @@ class UserLearningData extends React.Component {
key: 'learnState', key: 'learnState',
dataIndex: 'learnState', dataIndex: 'learnState',
render: (val, record) => { render: (val, record) => {
return <div>{LearnState[val].text}</div> return <div>{LearnState[val].text}</div>;
}, },
}, },
{ {
...@@ -300,7 +313,7 @@ class UserLearningData extends React.Component { ...@@ -300,7 +313,7 @@ class UserLearningData extends React.Component {
dataIndex: 'latelyLearnTime', dataIndex: 'latelyLearnTime',
sorter: true, sorter: true,
render: (val, record) => { render: (val, record) => {
return <div>{formatDate('YYYY-MM-DD H:i', val)}</div> return <div>{formatDate('YYYY-MM-DD H:i', val)}</div>;
}, },
}, },
{ {
...@@ -309,7 +322,7 @@ class UserLearningData extends React.Component { ...@@ -309,7 +322,7 @@ class UserLearningData extends React.Component {
dataIndex: 'startLearnTime', dataIndex: 'startLearnTime',
sorter: true, sorter: true,
render: (val, record) => { render: (val, record) => {
return <div>{formatDate('YYYY-MM-DD H:i', val)}</div> return <div>{formatDate('YYYY-MM-DD H:i', val)}</div>;
}, },
}, },
{ {
...@@ -333,7 +346,7 @@ class UserLearningData extends React.Component { ...@@ -333,7 +346,7 @@ class UserLearningData extends React.Component {
<span>/</span> <span>/</span>
<span>{record.courseNum}</span> <span>{record.courseNum}</span>
</div> </div>
) );
}, },
}, },
{ {
...@@ -350,28 +363,32 @@ class UserLearningData extends React.Component { ...@@ -350,28 +363,32 @@ class UserLearningData extends React.Component {
<span <span
className='operate-item' className='operate-item'
onClick={() => { onClick={() => {
this.UnbundEmployee(record) this.UnbundEmployee(record);
}}> }}>
解绑 解绑
</span> </span>
</div> </div>
) );
}, },
}, },
] ];
} }
return columns return columns;
} };
render() { render() {
const { dataSource, query, size, totalCount, userLearnDetailModalSHow, storeCustomerId, planId, unbundEmployeeModalVisible } = this.state const { dataSource, query, size, totalCount, userLearnDetailModalSHow, storeCustomerId, planId, unbundEmployeeModalVisible } = this.state;
return ( return (
<div className='user-learning-data'> <div className='user-learning-data'>
<div className='search-container'> <div className='search-container'>
<UserLearningDataFilter onChange={this.handleFetchDataList} /> <UserLearningDataFilter onChange={this.handleFetchDataList} />
</div> </div>
<div> <div>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.storeCustomerId} rowKey={(record) => record.storeCustomerId}
dataSource={dataSource} dataSource={dataSource}
columns={this.parselumns()} columns={this.parselumns()}
...@@ -388,15 +405,15 @@ class UserLearningData extends React.Component { ...@@ -388,15 +405,15 @@ class UserLearningData extends React.Component {
pageSize={size} pageSize={size}
total={totalCount} total={totalCount}
toPage={(page) => { toPage={(page) => {
const _query = { ...query, current: page + 1 } const _query = { ...query, current: page + 1 };
this.setState( this.setState(
{ {
query: _query, query: _query,
}, },
() => { () => {
this.handleFetchDataList() this.handleFetchDataList();
} }
) );
}} }}
onShowSizeChange={this.onShowSizeChange} onShowSizeChange={this.onShowSizeChange}
/> />
...@@ -412,14 +429,14 @@ class UserLearningData extends React.Component { ...@@ -412,14 +429,14 @@ class UserLearningData extends React.Component {
onClose={this.handleCloseUnbundEmployeeModal} onClose={this.handleCloseUnbundEmployeeModal}
storeCustomerId={storeCustomerId} storeCustomerId={storeCustomerId}
onConfirm={() => { onConfirm={() => {
this.handleFetchDataList() this.handleFetchDataList();
this.handleCloseUnbundEmployeeModal() this.handleCloseUnbundEmployeeModal();
}} }}
/> />
)} )}
</div> </div>
) );
} }
} }
export default withRouter(UserLearningData) export default withRouter(UserLearningData);
import React from 'react'; import React from 'react';
import _ from 'underscore'; import _ from 'underscore';
import { Table, Radio, Tabs, Modal, Input, message, Button, Tooltip } from 'antd'; import { Radio, Tabs, Modal, Input, message, Button, Tooltip } from 'antd';
import { PageControl } from '@/components'; import { PageControl, XMTable } from '@/components';
import college from '@/common/lottie/college';
import CourseService from '@/domains/course-domain/CourseService'; import CourseService from '@/domains/course-domain/CourseService';
import User from '@/common/js/user'; import User from '@/common/js/user';
...@@ -312,7 +313,7 @@ class SelectOperatorModal extends React.Component { ...@@ -312,7 +313,7 @@ class SelectOperatorModal extends React.Component {
return null; return null;
})} })}
<If condition={!hasCover}> <If condition={!hasCover}>
<img className='course-cover' src={"https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png"} alt='' /> <img className='course-cover' src={'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'} alt='' />
</If> </If>
<div> <div>
...@@ -384,19 +385,6 @@ class SelectOperatorModal extends React.Component { ...@@ -384,19 +385,6 @@ class SelectOperatorModal extends React.Component {
), ),
key: 'course', key: 'course',
dataIndex: 'course', dataIndex: 'course',
width: '40%',
title: (
<span>
<span>课程信息</span>
<Tooltip title='仅显示未关联课程,已关联课程不支持重复选择'>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: '400' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
key: 'course',
dataIndex: 'course',
width: '60%', width: '60%',
render: (val, record) => { render: (val, record) => {
const { coverUrl, scheduleVideoUrl } = record; const { coverUrl, scheduleVideoUrl } = record;
...@@ -471,7 +459,7 @@ class SelectOperatorModal extends React.Component { ...@@ -471,7 +459,7 @@ class SelectOperatorModal extends React.Component {
const { coverUrl } = record; const { coverUrl } = record;
return ( return (
<div className='course-info'> <div className='course-info'>
<img className='course-cover' src={coverUrl || "https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png"} alt='' /> <img className='course-cover' src={coverUrl || 'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png'} alt='' />
<div className='course-name'>{record.courseName}</div> <div className='course-name'>{record.courseName}</div>
</div> </div>
); );
...@@ -746,7 +734,11 @@ class SelectOperatorModal extends React.Component { ...@@ -746,7 +734,11 @@ class SelectOperatorModal extends React.Component {
</div> </div>
</div> </div>
<div> <div>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.liveCourseId} rowKey={(record) => record.liveCourseId}
dataSource={liveDataSource} dataSource={liveDataSource}
columns={this.parseLiveColumns()} columns={this.parseLiveColumns()}
...@@ -837,7 +829,11 @@ class SelectOperatorModal extends React.Component { ...@@ -837,7 +829,11 @@ class SelectOperatorModal extends React.Component {
</div> </div>
</div> </div>
<div> <div>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.id} rowKey={(record) => record.id}
dataSource={videoDataSource[videoCourseDivision]} dataSource={videoDataSource[videoCourseDivision]}
columns={this.parseVideoColumns()} columns={this.parseVideoColumns()}
...@@ -932,7 +928,11 @@ class SelectOperatorModal extends React.Component { ...@@ -932,7 +928,11 @@ class SelectOperatorModal extends React.Component {
</div> </div>
</div> </div>
<div> <div>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.id} rowKey={(record) => record.id}
dataSource={pictureDataSource} dataSource={pictureDataSource}
columns={this.parsePictureColumns()} columns={this.parsePictureColumns()}
......
import React, { useState, useRef, useEffect, useContext } from 'react' import React, { useState, useRef, useEffect, useContext } 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, Table } from 'antd';
import User from "@/common/js/user"; import User from '@/common/js/user';
import moment from 'moment'; import moment from 'moment';
import './userData.less' import './userData.less';
const { Search } = Input; const { Search } = Input;
const { Option } = Select; 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) {
const sortStatus: sortType = { const sortStatus: sortType = {
type: undefined type: undefined,
} };
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',
}, },
};
}
const queryRef = useRef({});
const queryRef = useRef({}); useEffect(() => {
queryExamUserData();
useEffect(() => { }, []);
queryExamUserData();
}, []) useEffect(() => {
queryRef.current = query;
useEffect(() => { queryExamUserDataList();
queryRef.current = query; }, [query]);
queryExamUserDataList();
}, [query]) function queryExamUserData() {
Service.Hades('public/hades/queryExamQuestionData', {
function queryExamUserData() { examId: props.examId,
Service.Hades('public/hades/queryExamQuestionData', { tenantId: User.getStoreId(),
examId: props.examId, userId: User.getStoreUserId(),
tenantId: User.getStoreId(), source: 0,
userId: User.getStoreUserId(), }).then((res) => {
source: 0 setUserData(res.result);
}).then((res) => { });
setUserData(res.result) }
}) function queryExamUserDataList() {
} Service.Hades('public/hades/queryExamQuestionDataList', {
...query,
examId: props.examId,
function queryExamUserDataList() { tenantId: User.getStoreId(),
Service.Hades('public/hades/queryExamQuestionDataList', { userId: User.getStoreUserId(),
...query, source: 0,
examId: props.examId, }).then((res) => {
tenantId: User.getStoreId(), setList(res.result.records);
userId: User.getStoreUserId(), setTotal(parseInt(res.result.total));
source: 0 if (!allData) {
}).then((res) => { setAllData(parseInt(res.result.total));
setList(res.result.records); }
setTotal(parseInt(res.result.total)) });
if (!allData) { }
setAllData(parseInt(res.result.total))
} const columns = [
}) {
} title: '序号',
dataIndex: 'sort',
width: 60,
const columns = [ render: (text: any, record: any, index: any) => <span>{index + 1}</span>,
},
{ {
title: "序号", title: '题目',
dataIndex: "sort", dataIndex: 'questionStem',
width: 60, ellipsis: true,
render: (text: any) => <span>{text + 1}</span>, width: 350,
}, render: (val: any) => {
{ var handleVal = val;
title: "题目", handleVal = handleVal.replace(/<(?!img|input).*?>/g, '');
dataIndex: "questionStem", handleVal = handleVal.replace(/<\s?input[^>]*>/gi, '_、');
ellipsis: true, handleVal = handleVal.replace(/\&nbsp\;/gi, ' ');
width: 350, return (
render: (val: any) => { <Tooltip
var handleVal = val; overlayClassName='aid-tool-list'
handleVal = handleVal.replace(/<(?!img|input).*?>/g, ""); title={<div style={{ maxWidth: 700, width: 'auto' }}>{handleVal}</div>}
handleVal = handleVal.replace(/<\s?input[^>]*>/gi, "_、"); placement='topLeft'
handleVal = handleVal.replace(/\&nbsp\;/gi, " "); overlayStyle={{ maxWidth: 700 }}>
return ( {handleVal}
<Tooltip </Tooltip>
overlayClassName="aid-tool-list" );
title={ },
<div style={{ maxWidth: 700, width: "auto" }}>{handleVal}</div> },
} {
placement="topLeft" title: '题型',
overlayStyle={{ maxWidth: 700 }} dataIndex: 'questionType',
> render: (text: any) => <span>{(questionTypeList as any)[text]}</span>,
{handleVal} filters: Object.keys(questionTypeList).map((key) => {
</Tooltip> return {
); text: (questionTypeList as any)[key],
}, value: key,
};
}, }),
{ },
title: "题型", {
dataIndex: "questionType", title: '本次正确率',
render: (text: any) => <span>{(questionTypeList as any)[text]}</span>, dataIndex: 'currentAccuracy',
filters: Object.keys(questionTypeList).map((key) => { sorter: true,
return { sortOrder: field === 'currentAccuracy' ? order : sortStatus.type,
text: (questionTypeList as any)[key], render: (text: any) => <span>{parseInt((text * 100) as any)}%</span>,
value: key },
} {
}), title: (
<div>
}, 历史正确率{' '}
{ <Tooltip overlayClassName='tool-list' title='包含本次考试正确率' placement='top' overlayStyle={{ maxWidth: 700 }}>
title: "本次正确率", {' '}
dataIndex: "currentAccuracy", <span style={{ color: 'rgba(191, 191, 191, 1)' }} className='icon iconfont'>
sorter: true, &#xe61d;
sortOrder: field === "currentAccuracy" ? order : sortStatus.type, </span>
render: (text: any) => <span>{parseInt(text * 100 as any)}%</span>, </Tooltip>
},
{
title: <div>历史正确率 <Tooltip
overlayClassName="tool-list"
title='包含本次考试正确率'
placement="top"
overlayStyle={{ maxWidth: 700 }}
> <span style={{ color: 'rgba(191, 191, 191, 1)' }} className="icon iconfont">&#xe61d;</span>
</Tooltip>
</div>,
dataIndex: "totalAccuracy",
render: (text: any) => <span>{parseInt(text * 100 as any)}%</span>,
},
];
function onChange(pagination: any, filters: any, sorter: any, extra: any) {
console.log(filters, sorter);
setfield(sorter.field);
setOrder(sorter.order)
console.log(sorter.field, sorter.order, (orderEnum as any)[sorter.field])
let _query: any = { ...queryRef.current };
console.log(filters.questionType)
if (filters.questionType) {
console.log(233232)
_query.questionType = filters.questionType;
_query.current = 1;
} else {
delete _query.questionType
}
_query.order = (orderEnum as any)[sorter.field][sorter.order]
setQuery(_query)
}
function download() {
Service.Hades('public/hades/exportExamData', {
// ...query,
examId: props.examId,
exportDataType: 'EXAM_QUESTION_DATA',
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
source: 0
}).then((res) => {
const dom = (document as any).getElementById("load-play-back-excel")
dom.setAttribute('href', res.result);
dom.click();
})
}
return <div className="rr">
<a
download
id="load-play-back-excel"
style={{ position: "absolute", left: "-10000px" }}
></a>
<div className="dataPanal">
{
!!examData.singleChoiceCnt && <div className="item">
<div className="num">{Math.round((examData.singleChoiceAccuracy || 0) * 100)}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fa;</span>单选题 <span>(共{examData.singleChoiceCnt}题)</span></div></div>
</div>
}
{
!!examData.multiChoiceCnt && <div className="item">
<div className="num">{Math.round((examData.multiChoiceAccuracy || 0) * 100)}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fb;</span>多选题<span>(共{examData.multiChoiceCnt}题)</span></div></div>
</div>
}
{
!!examData.judgeCnt && <div className="item">
<div className="num">{Math.round((examData.judgeAccuracy || 0) * 100)}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fc;</span>判断题<span>(共{examData.judgeCnt}题)</span></div></div>
</div>
}
{
!!examData.gapFillingCnt && <div className="item">
<div className="num">{Math.round((examData.gapFillingAccuracy || 0) * 100)}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fd;</span>填空题<span>(共{examData.gapFillingCnt}题)</span></div></div>
</div>
}
{
!!examData.indefiniteChoiceCnt && <div className="item">
<div className="num">{Math.round((examData.indefiniteChoiceAccuracy || 0) * 100)}%</div>
<div className="percent">正确率</div>
<div className="subTitle"><div className="type"><span className="icon iconfont">&#xe7fe;</span>不定项选择题 <span>(共{examData.indefiniteChoiceCnt}题)</span></div></div>
</div>
}
</div>
{
!!allData && <Button style={{ marginBottom: 12, marginTop: 12 }} onClick={download} >导出</Button>
}
<div className="content">
<Table
bordered
size="small"
columns={columns}
dataSource={list}
onChange={onChange}
pagination={false}
>
</Table>
{total > 0 &&
<PageControl
size="small"
current={query.current - 1}
pageSize={query.size}
total={total}
toPage={(page: any) => {
console.log(page)
let _query: any = { ...queryRef.current };
_query.current = page + 1;
setQuery(_query)
}}
/>
}
</div> </div>
),
dataIndex: 'totalAccuracy',
render: (text: any) => <span>{parseInt((text * 100) as any)}%</span>,
},
];
function onChange(pagination: any, filters: any, sorter: any, extra: any) {
console.log(filters, sorter);
setfield(sorter.field);
setOrder(sorter.order);
console.log(sorter.field, sorter.order, (orderEnum as any)[sorter.field]);
let _query: any = { ...queryRef.current };
console.log(filters.questionType);
if (filters.questionType) {
console.log(233232);
_query.questionType = filters.questionType;
_query.current = 1;
} else {
delete _query.questionType;
}
_query.order = (orderEnum as any)[sorter.field][sorter.order];
setQuery(_query);
}
function download() {
Service.Hades('public/hades/exportExamData', {
// ...query,
examId: props.examId,
exportDataType: 'EXAM_QUESTION_DATA',
tenantId: User.getStoreId(),
userId: User.getStoreUserId(),
source: 0,
}).then((res) => {
const dom = (document as any).getElementById('load-play-back-excel');
dom.setAttribute('href', res.result);
dom.click();
});
}
return (
<div className='rr'>
<a download id='load-play-back-excel' style={{ position: 'absolute', left: '-10000px' }}></a>
<div className='dataPanal'>
{!!examData.singleChoiceCnt && (
<div className='item'>
<div className='num'>{Math.round((examData.singleChoiceAccuracy || 0) * 100)}%</div>
<div className='percent'>正确率</div>
<div className='subTitle'>
<div className='type'>
<span className='icon iconfont'>&#xe7fa;</span>单选题 <span>(共{examData.singleChoiceCnt}题)</span>
</div>
</div>
</div>
)}
{!!examData.multiChoiceCnt && (
<div className='item'>
<div className='num'>{Math.round((examData.multiChoiceAccuracy || 0) * 100)}%</div>
<div className='percent'>正确率</div>
<div className='subTitle'>
<div className='type'>
<span className='icon iconfont'>&#xe7fb;</span>多选题<span>(共{examData.multiChoiceCnt}题)</span>
</div>
</div>
</div>
)}
{!!examData.judgeCnt && (
<div className='item'>
<div className='num'>{Math.round((examData.judgeAccuracy || 0) * 100)}%</div>
<div className='percent'>正确率</div>
<div className='subTitle'>
<div className='type'>
<span className='icon iconfont'>&#xe7fc;</span>判断题<span>(共{examData.judgeCnt}题)</span>
</div>
</div>
</div>
)}
{!!examData.gapFillingCnt && (
<div className='item'>
<div className='num'>{Math.round((examData.gapFillingAccuracy || 0) * 100)}%</div>
<div className='percent'>正确率</div>
<div className='subTitle'>
<div className='type'>
<span className='icon iconfont'>&#xe7fd;</span>填空题<span>(共{examData.gapFillingCnt}题)</span>
</div>
</div>
</div>
)}
{!!examData.indefiniteChoiceCnt && (
<div className='item'>
<div className='num'>{Math.round((examData.indefiniteChoiceAccuracy || 0) * 100)}%</div>
<div className='percent'>正确率</div>
<div className='subTitle'>
<div className='type'>
<span className='icon iconfont'>&#xe7fe;</span>不定项选择题 <span>(共{examData.indefiniteChoiceCnt}题)</span>
</div>
</div>
</div>
)}
</div>
{!!allData && (
<Button style={{ marginBottom: 12, marginTop: 12 }} onClick={download}>
导出
</Button>
)}
<div className='content'>
<Table bordered size='small' columns={columns} dataSource={list} onChange={onChange} pagination={false}></Table>
{total > 0 && (
<PageControl
size='small'
current={query.current - 1}
pageSize={query.size}
total={total}
toPage={(page: any) => {
console.log(page);
let _query: any = { ...queryRef.current };
_query.current = page + 1;
setQuery(_query);
}}
/>
)}
</div>
</div> </div>
);
} }
export default ExamData;
export default ExamData;
\ No newline at end of file
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
} }
.table-style { .table-style {
border: 1px solid #f0f0f0 !important; border: 1px solid #f0f0f0 !important;
margin-bottom: 70px;
} }
.ant-tabs { .ant-tabs {
color: #666666; color: #666666;
......
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